1

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

4

2 回答 2

4

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

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

  1. 创建一个新的 iOS“单一视图”项目
  2. 在 XCode 的项目导航器中创建一个名为 Lua 的组
  3. 将Lua下载中目录下的所有文件(除了lua.c、luac.c、lua.hpp和makefile)复制src到这个组
  4. 在 XCode 的项目导航器中创建一个名为 LuaSocket 的组
  5. 将LuaSockets下载目录中的所有文件(除了makefile、wsocket.c、wsocket.h)src复制到这个组
  6. 将该行添加#import "luasocket.h"到 LuaSocket 源中的文件 serial.h

此时,您应该能够构建和运行应用程序而不会出现任何错误。当然,它还没有真正做任何事情......

首先,我们要进行修改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 库,然后我们将使用NSBundle.

我们需要编辑 Lua 文件以删除任何包含requiresocket.core、mime.core的行,因为这比尝试require正确运行更简单。而且 socket.core 和 mime.core 已经被我们的 modified 初始化了luaL_openlibs,所以不需要require它们。

所以viewDidLoad看起来像这样:

- (void)viewDidLoad
{
  [super viewDidLoad];

  lua_State *L = luaL_newstate();
  luaL_openlibs(L);

  // Load socket.lua and mime.lua

  NSString *fp = [[NSBundle mainBundle] pathForResource:@"socket" ofType:@"lua"];
  luaL_dofile(L, [fp cStringUsingEncoding:NSUTF8StringEncoding]);

  fp = [[NSBundle mainBundle] pathForResource:@"mime" ofType:@"lua"];
  luaL_dofile(L, [fp cStringUsingEncoding:NSUTF8StringEncoding]);

  lua_settop(L, 0); // ignore return values from the calls to dofile


  // Now do something with the Lua state and LuaSockets

  NSString *script = @"res = mime.b64('LuaSocket', 'works')";
  luaL_dostring(L, [script cStringUsingEncoding:NSUTF8StringEncoding]);
  lua_getglobal(L, "res");
  const char *s  = luaL_checkstring(L, 1);
  NSLog(@"res = %@", [NSString stringWithCString:s encoding:NSUTF8StringEncoding]);
}

还有一些松散的结局,但这应该说明要点。您可以查看我在 Github 上创建的示例项目。在接下来的几天里,我会清理它并演示更多 LuaSocket 的功能。

于 2015-02-17T05:25:14.650 回答
2

我使用 2.0.2 版的 LuaSocket 和 5.1 版的 Lua。修改一些文件后[未知类型名称'luaL_reg'; 你的意思是“luaL_Reg”吗?] 我能够编译。还删除了 wsocket (.h & .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("socket") 但问题是它找不到核心 socket.lua:13: module 'socket.core' not found: no field package.preload['socket.core']

所以我认为你不会很快获得成功:)

于 2015-02-13T11:44:41.370 回答