如何在iOS应用程序中使用LuaSocket?

时间:2015-02-07 13:19:52

标签: ios objective-c lua cocoapods luasocket

我正在开发一个可以运行Lua脚本的iOS应用,我可以轻松地将基础lua支持与CocoaPods集成,但如何将LuaSocket库添加到它? LuaSocket包含一些C和一些Lua个文件,有没有人有想法?谢谢!

2 个答案:

答案 0 :(得分:4)

iOS 8允许动态框架(库)可能有更优雅的方法,但以下适用于Lua 5.2.3(,因为您使用Cocoapods,而5.2.3是Cocoapod提供的版本< / em>)和LuaSocket 3.0-rc1

注意我实际上并没有使用Cocoapod;在您的iOS项目中包含Lua非常简单,我觉得使用Cocoapods不值得。因人而异。由于路径差异,您可能需要对我下面描述的内容进行一些调整。

  1. 创建新的iOS“单一视图”项目
  2. 在XCode的项目导航器
  3. 中创建一个名为Lua的组
  4. 将Lua下载中的src目录中的所有文件(lua.c,luac.c,lua.hpp和makefile除外)复制到该组中
  5. 在XCode的项目导航器
  6. 中创建一个名为LuaSocket的组
  7. 将所有文件(makefile,wsocket.c,wsocket.h除外)从LuaSockets下载中的src目录复制到该组中
  8. 将行#import "luasocket.h"添加到LuaSocket源文件中的serial.h文件
  9. 此时您应该能够构建并运行应用程序而不会出现任何错误。当然,它还没有真正做任何事......

    首先,我们将修改luaL_openlibs,以便按如下方式初始化LuaSocket的C代码。

    在Lua源代码中,找到文件linit.c并更改

    static const luaL_Reg loadedlibs[] = {
      {"_G", luaopen_base},
      {LUA_LOADLIBNAME, luaopen_package},
      {LUA_COLIBNAME, luaopen_coroutine},
      {LUA_TABLIBNAME, luaopen_table},
      {LUA_IOLIBNAME, luaopen_io},
      {LUA_OSLIBNAME, luaopen_os},
      {LUA_STRLIBNAME, luaopen_string},
      {LUA_BITLIBNAME, luaopen_bit32},
      {LUA_MATHLIBNAME, luaopen_math},
      {LUA_DBLIBNAME, luaopen_debug},
      {NULL, NULL}
    };
    

      {"_G", luaopen_base},
      {LUA_LOADLIBNAME, luaopen_package},
      {LUA_COLIBNAME, luaopen_coroutine},
      {LUA_TABLIBNAME, luaopen_table},
      {LUA_IOLIBNAME, luaopen_io},
      {LUA_OSLIBNAME, luaopen_os},
      {LUA_STRLIBNAME, luaopen_string},
      {LUA_BITLIBNAME, luaopen_bit32},
      {LUA_MATHLIBNAME, luaopen_math},
      {LUA_DBLIBNAME, luaopen_debug},
      {"socket", luaopen_socket_core},
      {"mime", luaopen_mime_core},
      {NULL, NULL}
    };
    

    您需要在linit.c的顶部添加#include "luasocket.h"#include "mime.h"

    您还希望将其他几个C函数添加到此列表中,例如luaopen_socket_unix,但我会将它们作为练习留给读者。

    现在我们将转向LuaSocket中包含的各种Lua源文件,例如socket.lua和mime.lua。我们不是使用require加载这些内容,而是使用luaL_dofile执行它们。

    为了具体,假设我们想使用LuaSocket为视图控制器进行一些初始化。我们将在viewDidLoad中创建Lua状态,调用luaL_openlibs,初始化核心库和LuaSocket的C库,然后我们将使用来自{{{}的例程获取我们想要运行的Lua文件的文件路径。 1}}。

    我们需要编辑Lua文件以删除NSBundle socket.core,mime.core,的所有行,因为这比尝试require更简单行为正确。此外,socket.core和mime.core已经被修改后的require初始化,因此不需要luaL_openlibs

    所以require看起来像这样:

    viewDidLoad

    仍有一些松散的目标,但这应该说明要点。你可以看看我在Github上创建的example project。在接下来的几天里,我会清理它并展示更多LuaSocket的功能。

答案 1 :(得分:2)

我使用了LuaSocket的2.0.2版本和Lua的5.1版本。修改一些文件后[未知类型名称&#39; luaL_reg&#39 ;;你的意思是&luaL_Reg&#39;? ]我能够编译。还删除了wsocket(.h&amp; .c)文件。所以它正在编译。经过一番搜索,我发现Cocos2d-x源代码(3.0.4)也使用了luasocket文件夹(并且有liblua.a)。再次删除wsocket文件然后编译没有错误。我用了

    -(void)addBundlePathToLuaState:(lua_State*)L
   {
    lua_getglobal(L, "package");
   lua_getfield(L, -1, "path"); // get field "path" from table at top of stack (-1)

   const char* current_path_const = lua_tostring(L, -1); // grab path string from top of stack
   NSString* current_path = [NSString stringWithFormat:@"%s;%@/?.lua", current_path_const, [[NSBundle mainBundle]resourcePath]];

   lua_pop(L, 1); // get rid of the string on the stack we just pushed on line 5
   lua_pushstring(L, [current_path UTF8String]); // push the new one
   NSLog(@"path current %s", [current_path UTF8String]);
   lua_setfield(L, -2, "path"); // set the field "path" in table at -2 with value at top of stack
   lua_pop(L, 1); // get rid of package table from top of stack
     }

   int status;
   lua_State *La;
   La = luaL_newstate();
   NSBundle* myBundle = [NSBundle mainBundle];
   NSString* myImage = [myBundle pathForResource:@"a" ofType:@"lua"];
   const char *stringAsChar = [myImage cStringUsingEncoding:[NSString defaultCStringEncoding]];
   NSLog(@"mypath %s", stringAsChar);
   luaL_openlibs(La); /* Load Lua libraries */
/* Load the file containing the script we are going to run */
   status = luaL_loadfile(La, stringAsChar);
   NSString *luaFilePath = [[NSBundle mainBundle] pathForResource:@"a" ofType:@"lua"];
   [self addBundlePathToLuaState:La];

我的脚本使用本地socket = require(&#34; socket&#34;)但问题是它无法找到核心socket.lua:13:module&#39; socket.core&#39;未找到:     没有字段package.preload [&#39; socket.core&#39;]

所以我认为你很快就能获得成功:)