ObjectiveC-lua ブリッジに 2 つのライブラリを使用しています。1 つは、Lua 公式 Web ページで提供されている Lua ライブラリ (C API を使用) です。そのライブラリは、objectiveC オブジェクトを lua に渡すための API を提供していないため、この目的のために別のライブラリを選択しました。今のところ、Wax が唯一のオプションのようです。
このプログラムは、runLua() が呼び出されたときに開始され、そこで test.lua が呼び出されます。
iOS 実装
-(void) runLua{
[self initLua];
[self invokeLua:@"require test"];
}
-(void)initLua{
// initialize Lua and our load our lua file
L = luaL_newstate(); // create a new state structure for the interpreter
luaL_openlibs(L); // load all the standard libraries into the interpreter
lua_settop(L, 0);
initDone = TRUE;
}
-(void) invokeLua:(NSString*)luaSrcStr{
//NSLog(@"%@",luaSrcStr);
if(!initDone){
NSLog(@"inside invokeLua: not yet init");
[self initLua];
}
lua_settop(L, 0);
int ok = luaL_loadstring(L, [luaSrcStr UTF8String]);
if(ok == 0){
lua_getglobal(L,"debug");
lua_getfield(L,-1, "traceback");
lua_remove(L,-2);
lua_insert(L,-2);
ok = lua_pcall(L, 0, 0, -2);
if (ok != 0){
luaL_error(L, "cannot run lua file: %s",
lua_tostring(L, -1));
return;
}
}
test.lua
local testObject = myLib.newiOSObjWithName("TestObject")
testObject:setObjectLength(3.6)
myLib.passTestObjectToC(testObject)
1行目と2行目は実行しても問題ありませんが、3行目だけでエラーが発生します。
エラー
PANIC: unprotected error in call to Lua API (cannot run lua file: attempt to index a nil
value stack traceback:
[C]: in function 'passTestObjectToC'
...-451C-9F1D-9CE481B4F9A0/test.app/test.lua:6: in main chunk
[C]: in function 'require'
[string "..."]:3: in main chunk)
このエラーは、関数 passTestObjectToC が lua に見つからないことを示しているようです。この場合、luaL_openlibs(L) が呼び出されたときに関数が lua に登録されるため、これは当てはまりません。
私の推測では、wax_instance_create(luaState *L, ...) を使用して、objectiveC オブジェクトが lua に渡される場所で問題が発生します。オブジェクトを渡した後、Wax はおそらく luaState *L を変更したため、passTestObjectToC が既に登録されていることを覚えていません。
以下のようにCの実装。
C 実装
static int newiOSObjWithName(lua_State *L){
NSString *className = [NSString stringWithCString:lua_tostring(L, -1)
encoding:NSUTF8StringEncoding];
className = [className stringByReplacingCharactersInRange:NSMakeRange(0,1) withString:
[[className substringToIndex:1] uppercaseString]];
id classId = [[NSClassFromString(className) alloc] init];
luaopen_wax_instance(L);
wax_instance_create(L, classId, YES);
return 1;
}
static int passTestObjectToC(lua_State *L){
// something to be done here
return 0;
}
static const struct luaL_Reg myLib [] = {
{"newiOSObjWithName", newiOSObjWithName},
{"passTestObjectToC", passTestObjectToC},
{NULL, NULL}
}
int luaopen_mylib (lua_State *L){
luaL_register(L, "myLib", myLib);
return 1;
}
Lua ライブラリの linit.c
static const luaL_Reg lualibs[] = {
{"", luaopen_base},
{LUA_LOADLIBNAME, luaopen_package},
{LUA_TABLIBNAME, luaopen_table},
{LUA_IOLIBNAME, luaopen_io},
{LUA_OSLIBNAME, luaopen_os},
{LUA_STRLIBNAME, luaopen_string},
{LUA_MATHLIBNAME, luaopen_math},
{LUA_DBLIBNAME, luaopen_debug},
{"myLib", luaopen_mylib},
{NULL, NULL}
};
LUALIB_API void luaL_openlibs (lua_State *L) {
const luaL_Reg *lib = lualibs;
for (; lib->func; lib++) {
lua_pushcfunction(L, lib->func);
lua_pushstring(L, lib->name);
lua_call(L, 1, 0);
}
}
passTestObjectToC 呼び出しでエラーが発生する理由を教えてください。理由は何ですか?
利用可能な iOSObject を渡すための Wax 実装の例はありません。私はそれを見つけられませんでした。したがって、これが正しい方法であるかどうかはわかりません。ほとんどの例では、代わりに Wax を使用して iOS クラス/関数を Lua スクリプトに直接実装しています。