C++ 安全Lua调用C++;注册函数
大家好!我有一个C++应用程序嵌入的Lua作为脚本。非程序员编辑Lua脚本,然后C++应用程序调用Lua脚本,Lua脚本也调用C++注册函数。C++ 安全Lua调用C++;注册函数,c++,lua,C++,Lua,大家好!我有一个C++应用程序嵌入的Lua作为脚本。非程序员编辑Lua脚本,然后C++应用程序调用Lua脚本,Lua脚本也调用C++注册函数。 我使用Luaplus完成上述工作。我的问题是:当脚本编辑器出错,比如拼写错误参数时,C++应用程序崩溃!我能做些什么来防止这种情况发生?谢谢看看lua_cpcall和lua_pcall。它们都允许在c中对lua进行受保护的函数调用。如果它们返回非负数,则调用失败,lua堆栈仅包含错误字符串。在cpcalls情况下,堆栈未被修改。对于pcall,您需要查看
我使用Luaplus完成上述工作。我的问题是:当脚本编辑器出错,比如拼写错误参数时,C++应用程序崩溃!我能做些什么来防止这种情况发生?谢谢看看lua_cpcall和lua_pcall。它们都允许在c中对lua进行受保护的函数调用。如果它们返回非负数,则调用失败,lua堆栈仅包含错误字符串。在cpcalls情况下,堆栈未被修改。对于pcall,您需要查看lua_pushcclosure以安全地调用cfunction 您要做的是:创建一个c函数,其中包含所有需要的lua_*调用,例如loadfile和dofile。您可以使用lua_cpcall或lua_pushcclosure和lua_pcall调用此函数。这允许您检测t中是否发生错误 他是你传递给cpcall的函数 示例:
function hello() {
string hello_ = "Hello Lua!";
struct C {
static int call(lua_State* L) {
C *p = static_cast<C*>(lua_touserdata(L,-1));
lua_pushstring(L, p->str.c_str() );
lua_getglobal(L, "print");
lua_call(L, 1, 0); //ok
lua_pushstring(L, p->str.c_str() );
lua_getglobal(L, "notprint");
lua_call(L, 1, 0); //error -> longjmps
return 0; //Number of values on stack to 'return' to lua
}
const string& str;
} p = { hello_ };
//protected call of C::call() above
//with &p as 1st/only element on Lua stack
//any errors encountered will trigger a longjmp out of lua and
//return a non-0 error code and a string on the stack
//A return of 0 indicates success and the stack is unmodified
//to invoke LUA functions safely use the lua_pcall function
int res = lua_cpcall(L, &C::call, &p);
if( res ) {
string err = lua_tostring(L, -1);
lua_pop(L, 1);
//Error hanlder here
}
//load a .lua file
if( (res=luaL_loadfile(L, "myLuaFile.lua")) ) {
string err = lua_tostring(L, -1);
lua_pop(L, 1);
//res is one of
//LUA_ERRSYNTAX - Lua syntax error
//LUA_ERRMEM - Out of memory error
//LUE_ERRFILE - File not found/accessible error
}
//execute it
if( (res=lua_pcall(L,0,0,0)) ) {
string err = lua_tostring(L, -1);
lua_pop(L, 1);
// res is one of
// LUA_ERRRUN: a runtime error.
// LUA_ERRMEM: memory allocation error.
// LUA_ERRERR: error while running the error handler function (NULL in this case).
}
// try to call [a_int,b_str] = Foo(1,2,"3")
lua_getglobal(L,"Foo");
if( lua_isfunction(L,lua_gettop(L)) ) { //Foo exists
lua_pushnumber(L,1);
lua_pushnumber(L,2);
lua_pushstring(L,"3");
lua_pushvalue(L, -4); //copy of foo()
if( (res = lua_pcall(L, 3, 2, 0/*default error func*/)) ) {
string err = lua_tostring(L, -1);
lua_pop(L, 1);
//error: see above
}
int a_int = (int)lua_tointeger(L,-2);
string b_str = lua_tostring(L,-1);
lua_pop(L,2+1); //2 returns, + extra copy of Foo()
}
}
函数hello(){
string hello=“你好,Lua!”;
结构C{
静态int调用(lua_State*L){
C*p=静态施法(lua_-tuserdata(L,-1));
lua_pushstring(L,p->str.c_str());
lua_getglobal(左,“打印”);
lua_调用(L,1,0);//好的
lua_pushstring(L,p->str.c_str());
lua_getglobal(L,“notprint”);
lua_调用(L,1,0);//错误->longjmps
返回0;//堆栈上要“返回”到lua的值的数目
}
常量字符串&str;
}p={你好};
//上面的C::call()的受保护调用
//将&p作为Lua堆栈上的第一个/唯一元素
//遇到的任何错误都将触发longjmp out lua和
//在堆栈上返回非0错误代码和字符串
//返回0表示成功,堆栈未修改
//要安全地调用LUA函数,请使用LUA_pcall函数
int res=lua\u cpcall(L,&C::call,&p);
如果(res){
string err=lua_tostring(L,-1);
卢厄波普(L,1);
//这里有个错误
}
//加载一个.lua文件
if((res=luaL_loadfile(L,“myLuaFile.lua”)){
string err=lua_tostring(L,-1);
卢厄波普(L,1);
//res是其中之一
//LUA_ERRSYNTAX-LUA语法错误
//LUA_ERRMEM-内存不足错误
//LUE_ERRFILE-找不到文件/无法访问错误
}
//执行它
if((res=lua_pcall(L,0,0,0))){
string err=lua_tostring(L,-1);
卢厄波普(L,1);
//res是其中之一
//LUA_ERRRUN:运行时错误。
//LUA_ERRMEM:内存分配错误。
//LUA_err:运行错误处理函数时出错(本例中为NULL)。
}
//尝试调用[a_int,b_str]=Foo(1,2,“3”)
lua_getglobal(L,“Foo”);
如果(lua_isfunction(L,lua_gettop(L)){//Foo存在
lua_数(L,1);
lua_数(L,2);
lua_推进管柱(L,“3”);
lua_pushvalue(L,-4);//foo()的副本
if((res=lua_pcall(L,3,2,0/*默认错误func*/)){
string err=lua_tostring(L,-1);
卢厄波普(L,1);
//错误:见上文
}
int a_int=(int)lua_tointeger(L,-2);
字符串b_str=lua_tostring(L,-1);
lua_pop(L,2+1);//2返回,+Foo()的额外副本
}
}