如何在 iOS 应用程序中使用 LuaSocket?
How can I use LuaSocket in iOS app?
我正在开发一个 iOS 应用程序可以 运行 Lua
脚本,我可以轻松地将基础 lua
支持与 CocoaPods
集成,但是如何我可以将 LuaSocket
库添加到其中吗? LuaSocket
包含一些 C
和一些 Lua
文件,有人有想法吗?谢谢!
我使用 LuaSocket 的 2.0.2 版本和 Lua 的 5.1。修改部分文件后[ Unknown type name '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: 找不到模块 'socket.core':
没有字段 package.preload['socket.core']
所以我认为你不会很快获得成功:)
使用 iOS 8 允许动态框架(库)可能有更优雅的方法,但以下方法适用于 Lua 5.2.3(因为您使用的是 Cocoapods , 5.2.3 是 Cocoapod 提供的版本) 和 LuaSocket 3.0-rc1.
请注意,我实际上并没有使用 Cocoapod;在您的 iOS 项目中包含 Lua 非常简单,我发现不值得使用 Cocoapods。 YMMV。由于路径差异,您可能需要对我在下面描述的内容进行一些调整。
- 新建一个iOS'Single View'项目
- 在 XCode 的项目导航器中创建一个名为 Lua 的组
- 将 Lua 下载的
src
目录中的所有文件(lua.c、luac.c、lua.hpp 和 makefile 除外)复制到该组
- 在 XCode 的项目导航器中创建一个名为 LuaSocket 的组
- 将 LuaSockets 下载中
src
目录中的所有文件(makefile、wsocket.c、wsocket.h 除外)复制到该组
- 将
#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
,但我会将它们作为 reader 的练习。
现在我们将转向 LuaSocket 中包含的各种 Lua 源文件,例如 socket.lua 和 mime.lua。我们将使用 luaL_dofile
.
来执行它们,而不是使用 require
来加载它们
为了具体起见,假设我们要使用LuaSocket 为我们的视图控制器做一些初始化。我们将在 viewDidLoad
中创建 Lua 状态,调用 luaL_openlibs
,以初始化核心库和 LuaSocket 的 C 库,然后我们将获得 Lua 个文件,我们想要 运行 使用 NSBundle
.
中的例程
我们需要编辑 Lua 文件以删除 require
socket.core、mime.core、 等 的任何行因为这比尝试让 require
正确运行要简单。而且socket.core和mime.core已经被我们修改后的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 上创建的 example project。在接下来的几天里,我会清理它并演示更多 LuaSocket 的功能。
我正在开发一个 iOS 应用程序可以 运行 Lua
脚本,我可以轻松地将基础 lua
支持与 CocoaPods
集成,但是如何我可以将 LuaSocket
库添加到其中吗? LuaSocket
包含一些 C
和一些 Lua
文件,有人有想法吗?谢谢!
我使用 LuaSocket 的 2.0.2 版本和 Lua 的 5.1。修改部分文件后[ Unknown type name '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: 找不到模块 'socket.core': 没有字段 package.preload['socket.core']
所以我认为你不会很快获得成功:)
使用 iOS 8 允许动态框架(库)可能有更优雅的方法,但以下方法适用于 Lua 5.2.3(因为您使用的是 Cocoapods , 5.2.3 是 Cocoapod 提供的版本) 和 LuaSocket 3.0-rc1.
请注意,我实际上并没有使用 Cocoapod;在您的 iOS 项目中包含 Lua 非常简单,我发现不值得使用 Cocoapods。 YMMV。由于路径差异,您可能需要对我在下面描述的内容进行一些调整。
- 新建一个iOS'Single View'项目
- 在 XCode 的项目导航器中创建一个名为 Lua 的组
- 将 Lua 下载的
src
目录中的所有文件(lua.c、luac.c、lua.hpp 和 makefile 除外)复制到该组 - 在 XCode 的项目导航器中创建一个名为 LuaSocket 的组
- 将 LuaSockets 下载中
src
目录中的所有文件(makefile、wsocket.c、wsocket.h 除外)复制到该组 - 将
#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
,但我会将它们作为 reader 的练习。
现在我们将转向 LuaSocket 中包含的各种 Lua 源文件,例如 socket.lua 和 mime.lua。我们将使用 luaL_dofile
.
require
来加载它们
为了具体起见,假设我们要使用LuaSocket 为我们的视图控制器做一些初始化。我们将在 viewDidLoad
中创建 Lua 状态,调用 luaL_openlibs
,以初始化核心库和 LuaSocket 的 C 库,然后我们将获得 Lua 个文件,我们想要 运行 使用 NSBundle
.
我们需要编辑 Lua 文件以删除 require
socket.core、mime.core、 等 的任何行因为这比尝试让 require
正确运行要简单。而且socket.core和mime.core已经被我们修改后的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 上创建的 example project。在接下来的几天里,我会清理它并演示更多 LuaSocket 的功能。