设置:我在C / C ++环境中使用Lua。
我在磁盘上有几个lua文件。这些被读入内存,并且在运行时期间可以使用一些仅有内存的lua文件。想想例如一个编辑器,带有其他未保存的lua文件。
所以,我的记忆中有一个list<identifier, lua_file_content>
。其中一些文件中包含require
个语句。当我尝试将所有这些文件加载到lua实例(目前通过lua_dostring
)时,我得到attempt to call global require (a nil value)
。
是否有可能提供require
函数,该函数替换旧函数并仅使用内存文件中提供的函数(这些文件位于C端)?
是否有另一种方法允许require
在这些文件中没有磁盘上的所需文件?
一个例子是只从内存加载lua stdlib而不改变它。 (这实际上是我的测试用例。)
答案 0 :(得分:9)
为什么不向require
添加功能,而不是替换package.loaders
?代码几乎相同。
int my_loader(lua_State* state) {
// get the module name
const char* name = lua_tostring(state);
// find if you have such module loaded
if (mymodules.find(name) != mymodules.end())
{
luaL_loadbuffer(state, buffer, size, name);
// the chunk is now at the top of the stack
return 1;
}
// didn't find anything
return 0;
}
// When you load the lua state, insert this into package.loaders
http://www.lua.org/manual/5.1/manual.html#pdf-package.loaders
答案 1 :(得分:5)
一个非常简单的C ++函数可以模仿require
:(伪代码)
int my_require(lua_State* state) {
// get the module name
const char* name = lua_tostring(state);
// find if you have such module loaded
if (mymodules.find(name) != mymodules.end())
luaL_loadbuffer(state, buffer, size, name);
// the chunk is now at the top of the stack
lua_call(state)
return 1;
}
将此功能公开为Lua require
,你很高兴。
我还想补充一点,以完全模仿require
的行为,你可能需要处理package.loaded
,以避免代码被加载两次。
答案 2 :(得分:2)
lua 5.2中没有package.loaders 它现在称为package.searchers。
#include <stdio.h>
#include <string>
#include <lua.hpp>
std::string module_script;
int MyLoader(lua_State *L)
{
const char *name = luaL_checkstring(L, 1); // Module name
// std::string result = SearchScript(name); // Search your database.
std::string result = module_script; // Just for demo.
if( luaL_loadbuffer(L, result.c_str(), result.size(), name) )
{
printf("%s", lua_tostring(L, -1));
lua_pop(L, 1);
}
return 1;
}
void SetLoader(lua_State* L)
{
lua_register(L, "my_loader", MyLoader);
std::string str;
// str += "table.insert(package.loaders, 2, my_loader) \n"; // Older than lua v5.2
str += "table.insert(package.searchers, 2, my_loader) \n";
luaL_dostring(L, str.c_str());
}
void SetModule()
{
std::string str;
str += "print([[It is add.lua]]) \n";
str += "return { func = function() print([[message from add.lua]]) end } \n";
module_script=str;
}
void LoadMainScript(lua_State* L)
{
std::string str;
str += "dev = require [[add]] \n";
str += "print([[It is main.lua]]) \n";
str += "dev.func() \n";
if ( luaL_loadbuffer(L, str.c_str(), str.size(), "main") )
{
printf("%s", lua_tostring(L, -1));
lua_pop(L, 1);
return;
}
}
int main()
{
lua_State* L = luaL_newstate();
luaL_openlibs(L);
SetModule(L); // Write down module in memory. Lua not load it yet.
SetLoader(L);
LoadMainScript(L);
lua_pcall(L,0,0,0);
lua_close(L);
return 0;
}