C++ 编译 Lua 从而使 Lua 利用 C++ 异常

看 ldo.c 前面的 LUAI_THROW LUAI_TRY 等宏就是做的这个事情。所以,如果你用 C++ 做宿主语言,就应该用 C++ 编译器编译 Lua 库。

并且在下面一段中的一句话给出了如果用 C++ 做宿主语言,应该用 C++ 编译 Lua 的原因:

Lua 在内部发生异常时,VM 会在 C 的 stack frame 上直接跳至之前设置的恢复点,然后 unwind lua vm 层次上的 lua stack 。lua stack (CallInfo 结构)在捕获异常后是正确的,但 C 的 stack frame 的处理未必如你的宿主程序所愿。也就是 RAII 机制很可能没有被触发。

上面这段话的意义在于在 Lua 中使用 C++ 异常,如果 Lua 抛出异常,此时走 C++ 异常机制,可确保对象被正确销毁,即析构函数被调用,也就保证了 RAII 机制。

举个例子,如下代码片段,在创建 C++ 对象 t 后发生了异常,此时使用 C++ 编译的 Lua 库,可保证 t 的析构函数会被调用。

static int
test_func(lua_State *L) {
Test t;
luaL_error(“there is an error here”); //www.lover27.com 模拟 Lua C API 抛出异常
}
下面测试使用 C 和 C++ 编译的 Lua 库,来验证对象的析构函数是否会被调用。

编译 Lua 。
编译 C 版本 Lua 库:make linux 。库名为 liblua.a 。
编译 C++ 版本 Lua 库:make linux CC=“g++” 。修改库名为 libluacc.a 。

编写 C++ 宿主程序,并编译。
#include
#include

#ifndef LUA_CLIB
#include <lua/lua.h>
#include <lua/lualib.h>
#include <lua/lauxlib.h>
#else
#include <lua/lua.hpp>
#endif

using namespace std;

class Test {
public:
Test()
{
cout << “Test ctor:” << this << endl;
}

~Test()
{
    cout << "Test dctor:" << this <<endl;
}

};

static int
entry(lua_State *L) {
cout << “enter entry” << endl;
Test t;
luaL_error(L, “there is an error”);
cout << “exit entry” << endl;
return 0;
}

int
main() {
lua_State *L = luaL_newstate();
lua_pushcfunction(L, entry);
if (lua_pcall(L, 0, 0, 0)) {
cout << “pcall error:” << lua_tostring(L, -1) << endl;
}
cout << “after function entry” << endl;
lua_close(L);
return 0;
}
Makefile 如下:

tc:
g++ -Wall -g -DLUA_CLIB -o tc main.cc ./liblua.a
tcc:
g++ -Wall -g -o tcc main.cc ./libluacc.a

clean:
rm -f tc
rm -f tcc
运行 Lua 的 C 版本库对应的可执行文件 tc 和 Lua 的 C++ 版本库对应的可执行文件 tcc 。
运行 tc 输出如下:

$ ./tc
enter entry
Test ctor:0x7ffdfd7b4677
pcall error:there is an error
after function entry
运行 tcc 输出如下:

$ ./tcc
enter entry
Test ctor:0x7ffd25d86e47
Test dctor:0x7ffd25d86e47
pcall error:there is an error
after function entry
可发现运行 tcc 时,对象 t 的析构函数执行了。

总之,要小心处理 Lua 中的异常,特别是在 C++ 中。在 C++ 中,即使 Lua 中的异常使用了 C++ 异常,要捕获 Lua 中抛出的异常,也只能通过 lua_pcall 或者 lua_resume 而不能使用 try catch 。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值