文档章节

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

ylme
 ylme
发布于 08/10 22:08
字数 783
阅读 604
收藏 4
Lua

Lua 源码文件 ldo.c 中有如下说明:

LUAI_THROW/LUAI_TRY define how Lua does exception handling. By default, Lua handles errors with exceptions when compiling as C++ code

搜索使用 C++ 编译 Lua 时,也有提到使用 C++ 异常: According to the Lua Wiki, if Lua 5.1 or later is compiled as C++, it will use C++ exceptions.

阅读这篇博客时,云大也提到:

看 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"); // 模拟 Lua C API 抛出异常
}

下面测试使用 C 和 C++ 编译的 Lua 库,来验证对象的析构函数是否会被调用。

  • 编译 Lua 。

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

  • 编写 C++ 宿主程序,并编译。
#include <iostream>
#include <string>

#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 。详情阅读这里

© 著作权归作者所有

ylme
粉丝 15
博文 47
码字总数 51044
作品 0
广州
程序员
私信 提问
FFLIB之FFLUA——C++嵌入Lua&扩展Lua利器

摘要: 在使用C++做服务器开发中,经常会使用到脚本技术,Lua是最优秀的嵌入式脚本之一。Lua的轻量、小巧、概念之简单,都使他变得越来越受欢迎。本人也使用过python做嵌入式脚本,二者各有特...

知然
2013/01/27
0
0
cocos2d-x lua代码臃肿,有没有解决方案?客户端动态更新其他好建议吗?

近期开始学习并使用lua。软件分层的思想全世界可以用。但是纯lua的开发模式实现却很难使用多态和封装,也许是我水平低。面临的实际问题却是代码臃肿,不断的循环遍历(我在做解析文本)。我有...

王敬哲
2014/06/10
1K
4
用LuaBridge为Lua绑定C/C++对象

最近为了总结Lua绑定C/C++对象的各种方法、第三方库和原理,学习了LuaBridge库为Lua绑定C/C++对象,下面是学习笔记,实质是对该库的Reference Manual基本上翻译了一遍,学习过程中测试代码,...

shezjl
2015/10/26
214
0
(转)LUA与python根本就不具有可比性

网上经常看到别人拿lua与python来进行对比,但是,本人认为,lua与python根本就不具有可比性.原因如下: 1、两者的定位不同。python的定位在于自身的独立开发,即是说python定位于自己能解决所有...

Yisen
2011/06/27
10.8K
6
luabind 0.9.1版本尝试

luabind 0.9.1版本尝试 http://www.rasterbar.com/products/luabind 1. 编译luabind 0.9.1 linux版本 编译luabind需要bjam binary。 直接copy boost/1.37.0目录中编译好的bjam binary到~/bin......

zero-li
2014/01/14
363
0

没有更多内容

加载失败,请刷新页面

加载更多

OSChina 周日乱弹 —— 我,小小编辑,食人族酋长

Osc乱弹歌单(2019)请戳(这里) 【今日歌曲】 @宇辰OSC :分享娃娃的单曲《飘洋过海来看你》: #今日歌曲推荐# 《飘洋过海来看你》- 娃娃 手机党少年们想听歌,请使劲儿戳(这里) @宇辰OSC...

小小编辑
今天
443
10
MongoDB系列-- SpringBoot 中对 MongoDB 的 基本操作

SpringBoot 中对 MongoDB 的 基本操作 Database 库的创建 首先 在MongoDB 操作客户端 Robo 3T 中 创建数据库: 增加用户User: 创建 Collections 集合(类似mysql 中的 表): 后面我们大部分都...

TcWong
今天
4
0
spring cloud

一、从面试题入手 1.1、什么事微服务 1.2、微服务之间如何独立通讯的 1.3、springCloud和Dubbo有哪些区别 1.通信机制:DUbbo基于RPC远程过程调用;微服务cloud基于http restFUL API 1.4、spr...

榴莲黑芝麻糊
今天
3
0
Executor线程池原理与源码解读

线程池为线程生命周期的开销和资源不足问题提供了解决方 案。通过对多个任务重用线程,线程创建的开销被分摊到了多个任务上。 线程实现方式 Thread、Runnable、Callable //实现Runnable接口的...

小强的进阶之路
昨天
7
0
maven 环境隔离

解决问题 即 在 resource 文件夹下面 ,新增对应的资源配置文件夹,对应 开发,测试,生产的不同的配置内容 <resources> <resource> <directory>src/main/resources.${deplo......

之渊
昨天
8
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部