2014-03-18 91 views
2

我是lua的新手,這可能很簡單,但我無法弄清楚。我做了整夜搜索,在這裏閱讀一些帖子,但不是我想要的。我終於找到了一個我不滿意的跛腳解決方案,所以我在這裏尋求幫助。我想知道,每個iPhone應用程序都有一個資源包,並且lua腳本隨該包一起發佈。我想在C++中嵌入lua,並且此程序將作爲iPhone上的應用程序的一部分運行。lua require功能在iOS上找不到我需要的文件

// I printed out the bundle path: 
bundle directory /var/mobile/Applications/C6CEF090-B99A-4B9B-ADAC-F0BEF46B6EA4/LuaThirdTry.app 

說我有在同一文件夾兩個腳本文件(main.lua,mylib.lua),我把它們放在我的Xcode項目,舉辦這樣的:

somefolder 
|--main.lua 
|--mylib.lua 

和main.lua是如下:

--main.lua 
print(package.path) 
require("mylib") 

很明顯,我想從mylib.lua使用代碼,但是,我從Lua VM錯誤:

/usr/local/share/lua/5.2/?.lua;/usr/local/share/lua/5.2/?/init.lua;/usr/local/lib/lua/5.2/?.lua;/usr/local/lib/lua/5.2/?/init.lua;./?.lua 
PANIC: unprotected error in call to Lua API (...090-B99A-4B9B-ADAC-F0BEF46B6EA4/LuaThirdTry.app/test.lua:5: module 'mylib' not found: 
    no field package.preload['mylib'] 
    no file '/usr/local/share/lua/5.2/mylib.lua' 
    no file '/usr/local/share/lua/5.2/mylib/init.lua' 
    no file '/usr/local/lib/lua/5.2/mylib.lua' 
    no file '/usr/local/lib/lua/5.2/mylib/init.lua' 
    no file './mylib.lua' 
    no file '/usr/local/lib/lua/5.2/mylib.so' 
    no file '/usr/local/lib/lua/5.2/loadall.so' 
    no file './mylib.so') 

當我添加一行修改package.path,我得到了它正常運行:

--main.lua modified 
print(package.path) 
package.path = package.path .. ";/var/mobile/Applications/C6CEF090-B99A-4B9B-ADAC-F0BEF46B6EA4/LuaThirdTry.app/?.lua" 
require("mylib") 

但是,這是一個絕對路徑,絕對應該避免。 解決這個問題的一種方法是從c提供lua函數,它將運行時lua文件包中lua文件的完整路徑返回給lua腳本,並將package.path與該路徑連接起來,但我認爲不應該成爲這樣做的「官方」方式。

我注意到「./?.lua」在package.path變量中,我只是想知道爲什麼mylib.lua找不到,是不是針對同一目錄中的文件?

不好意思,所以問題是:我如何在iOS環境中體面地「要求」?

回答

0

最有可能的是「。」不是包含main.lua的文件夾,而是一個工作目錄(例如xcode從哪裏運行)。運行腳本的應用程序可能通過的路徑運行它,就像

lua /full/path/to/your/main.lua 

所以具有LUA_PATH ./?.lua這裏沒有幫助。相反,您應該讓腳本運行一個命令來確定它的運行位置,然後將其附加到package.path。這應該是arg[0]的路徑部分。所以,你可以試試(未測試):

local scriptPath = arg[0] 
local dir = string.match(scriptPath, '^.*/') 
package.path = package.path .. ';' .. dir .. '?.lua' 

arg自動地被解釋稀少,看到Section 6 of Lua ref man

你絕對不需要C來做你想做的事。

+0

Schollii嗨,感謝您的回答,我不知道如何檢索運行腳本的路徑,任何線索? –

+0

這就是我上面顯示的內容:arg數組是由解釋器爲你自動填充的。我已經更新了答案,hth。 – Schollii

+0

是的,它完美地與獨立的lua解釋器一起工作,我試過了,謝謝。可悲的是,我似乎沒有arg可用於嵌入在C++代碼中的lua。 –

1

好的,我終於找到了一個很好的答案,工作完成,感謝this answer

所以,解決的辦法是修改中的C++代碼的路徑,添加此功能

#include <string> 

int setLuaPath(lua_State* L, const char* path) { 
    lua_getglobal(L, "package"); 
    lua_getfield(L, -1, "path"); // get field "path" from table at top of stack (-1) 
    std::string cur_path = lua_tostring(L, -1); // grab path string from top of stack 
    cur_path.append(";"); // do your path magic here 
    cur_path.append(path); 
    lua_pop(L, 1); // get rid of the string on the stack we just pushed on line 5 
    lua_pushstring(L, cur_path.c_str()); // push the new one 
    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 
    return 0; // all done! 
} 

,然後調用這個函數初始化時lua_State:

// yourfile.cpp 
void runLua() { 
    lua_State *L; 
    L = luaL_newstate(); 
    luaL_openlibs(L); 

    OCCaller oc_caller; 
    std::string bundlePath = oc_caller.get_ios_bundle_path(); 
    bundlePath.append("/?.lua"); 
    setLuaPath(L, bundlePath.c_str()); 

    .... 
} 

您oc_caller類可能看起來像這樣的:

// OCCaller.h 
#ifndef __LuaThirdTry__OCCaller__ 
#define __LuaThirdTry__OCCaller__ 

#include <iostream> 

class OCCaller { 
public: 
    OCCaller(); 
    ~OCCaller(); 
    std::string get_ios_bundle_path(); 

}; 

#endif 

IMPL文件:

// OCCaller.mm 
#include "OCCaller.h" 
#import <Foundation/Foundation.h> 

OCCaller::OCCaller() { } 
OCCaller::~OCCaller() { } 

std::string OCCaller::get_ios_bundle_path() { 
    NSString *bundlePath = [[NSBundle mainBundle]resourcePath]; 
    return std::string([bundlePath UTF8String]); 
} 
0

這是修改苔蘚植物的答案。對我而言,這太複雜了。我也不確定他爲什麼要做所有這些額外的類,並使用C++字符串代替NSString。這裏是我的修訂,並在此基礎上的解決方案有望更容易理解的iOS代碼:

-(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 
    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 
} 
相關問題