我正在将Lua作为脚本语言实现到Windows应用程序中。由于应用程序的结构,打印输出未使用流式io,例如stdout
和stderror
。
我设法覆盖了Luaprint
以适合我的结构...
lua_register(L,"print", cs_print);
...但是如何在不使用流的情况下覆盖调试打印输出的所有错误?我需要在函数中处理此问题(类似于print
)。
经过大量的Google搜寻后,我想到了这个解决方案来获取编译器和运行时错误消息,以及重定向标准的Lua打印功能。
我使用C ++ Builder,但我认为它对寻找相同答案的任何人都有用。该脚本在TScriptLua对象实例中运行,并且为了针对正确的脚本实例映射Lua状态,我使用std :: map列表查找对象指针。
// list for mapping Lua state with object pointers.
static std::map<lua_State*,TScriptLua*> LuaObjMap;
接下来是一个内联函数,用于从Lua状态指针获取对象指针。
extern "C" {
// Inline to map Lua state pointer to object pointer
static inline TScriptLua* GetScriptObject(lua_State* L) {
return LuaObjMap.find(L)->second;
}
此功能将取代标准的Lua打印功能。对象指针(f)在其基类中具有一个名为Out()的成员函数,该成员函数将在关联的窗口控件中输出一个char缓冲区。
// New Lua print function
static int cs_print (lua_State *L) {
// Map Lua state to object
TScriptLua* f = GetScriptObject(L);
if (f) {
int count = lua_gettop(L);
for (int i=1; i <= count; ++i) {
const char *str = lua_tostring(L, i); // Get string
size_t len = lua_rawlen(L,i); // Get string length
// Output string.
f->Out(str,len);
}
}
return 0;
}
这是我的错误打印例程,将显示编译器/运行时错误。至于Lua打印功能,则再次使用f-> Out打印错误消息。
// Error print routine
static int cs_error(lua_State *L, char *msg) {
// Map Lua state to object
TScriptLua* f = GetScriptObject(L);
// Get error message
AnsiString m = String(msg) + " " + String(lua_tostring(L, -1));
// "print" error message
f->Out(m.c_str(),m.Length());
// Clenaup Lua stack
lua_pop(L, 1);
return 0;
}
} // <--- End extern C
这是实际的负载和运行成员。创建新的Lua状态后,它将与映射列表中的该对象关联。然后,它使用luaL_loadbuffer()从Rich编辑控件中加载脚本,检查编译器错误,并使用lua_pcall()运行已编译的脚本。
void __fastcall TScriptLua::Compile(void) {
// Create new Lua state
lua_State *L = luaL_newstate();
// Store mapping Lua state --> object
LuaObjMap.insert( std::pair<lua_State*,TScriptLua*>(L,this) );
// Override Lua Print
lua_register(L,"print", cs_print);
// Load and compile script
AnsiString script(Frame->Script_RichEdit->Text);
if (luaL_loadbuffer(L,script.c_str(),script.Length(),AnsiString(Name).c_str()) == 0) {
if (lua_pcall(L, 0, 0, 0)) // Run loaded Lua script
cs_error(L, "Runtime error: "); // Print runtime error
} else {
cs_error(L, "Compiler error: "); // Print compiler error
}
// Close Lua state
lua_close(L);
// Remove Lua --> object mapping
LuaObjMap.erase( LuaObjMap.find(L) );
}
这不是我的最终解决方案,但到目前为止,它可以解决问题。我认为最好的办法是将流处理写入TScriptLua对象中,这样我就可以直接将其注册到Lua中。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句