使用 tolua++ 绑定结构体和 ctor/dtor
假设我想将一段代码绑定到 Lua,如下所示:
typedef struct bar {
void * some_data;
} bar;
bar * bar_create(void);
void bar_do_something(bar * baz);
void bar_free(bar * baz);
我想从 Lua 脚本创建这些对象,而不是显式管理它们的生命周期。最好,我希望我的脚本编写
require "foo"
local baz = foo:bar()
baz:do_something()
baz = nil
问题:为了按预期工作,我需要以某种方式告诉 tolua++ bar_create 和 bar_free 作为 bar 的构造函数/析构函数。我该怎么做?对于类,tolua++ 声称自动使用它们的 ctor/dtor,但是对于结构呢?
我能想到的最好的办法是 foo.pkg 的定义:
module foo {
struct bar {
static tolua_outside bar_create @ create();
tolua_outside bar_do_something @ do_something();
tolua_outside bar_free @ free();
};
}
这意味着我必须显式调用 create() 和 free() 。
Let's say I want to bind a piece of code to Lua that looks like this:
typedef struct bar {
void * some_data;
} bar;
bar * bar_create(void);
void bar_do_something(bar * baz);
void bar_free(bar * baz);
I want to create these objects from a Lua script, and not explicitly manage their lifetime. Prefereably, I would like my script to write
require "foo"
local baz = foo:bar()
baz:do_something()
baz = nil
Problem: For that to work as expected, I need to somehow tell tolua++ about bar_create and bar_free being the constructor/destructor for bar. How do I do that? For classes, tolua++ claims to automatically use their ctor/dtor, but for structs?
The best thing I can come up with is this definition of foo.pkg:
module foo {
struct bar {
static tolua_outside bar_create @ create();
tolua_outside bar_do_something @ do_something();
tolua_outside bar_free @ free();
};
}
which would mean I have to call create() and free() explicitly.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
可以使用 tolua++ 将
bar
函数导入到 Lua 中,并进行包装以生成对象样式的接口,包括垃圾收集。为了演示参数的传递,我将
bar
接口更改为并编写了一个测试实现,在以下情况下打印出
x
、y
等函数被调用。bar_create()
Lua 函数返回一个用户数据值。 Lua 通过调用存储在数据元表中的 __gc 方法来释放此类用户数据。给定一个userdata
值和一个析构函数gc
,__gc
方法将被覆盖,以便它首先调用gc
,然后调用原来的gc
方法:相同类型的Userdata共享相同的元表;因此,对于每个类,wrap_garbage_collector() 函数应该只调用一次(假设 tolua++ 的元表构造一次并仅在退出时释放)。
在这个答案的底部是一个完整的
bar.pkg
文件,它导入bar
函数并将一个bar
类添加到名为 <代码>foo。foo
模块被加载到解释器中(请参阅我的 SO tolua++ 示例)并按如下方式使用:测试实现打印出发生的情况:
下面
bar
类的构造有点复杂:在给定构造函数、析构函数和类方法的情况下,build_class()
实用程序返回一个类(Lua 表)。毫无疑问需要进行调整,但作为原型演示,该示例应该没问题。The
bar
functions can be imported into Lua using tolua++ and wrapped to yield an object-style interface, garbage collection included.To demonstrate the passing of arguments, I have changed the
bar
interface toand written a test implementation that prints out
x
,y
, etc. when the functions are called.The
bar_create()
Lua function returns a userdata value. Lua deallocates such user data by calling the__gc
method stored in the metatable of the data. Given auserdata
value and a destructorgc
, the__gc
method is overwritten such that it first callsgc
and then calls the originalgc
method:Userdata of the same type share the same metatable; therefore the
wrap_garbage_collector()
function should be called only once for each class (assuming that tolua++'s metatables are constructed once and deallocated only at exit).At the bottom of this answer is a complete
bar.pkg
file that imports thebar
functions and adds abar
class to a Lua module namedfoo
. Thefoo
module is loaded into the interpreter (see for example my SO tolua++ example) and used like this:The test implementation prints out what happens:
The construction of the
bar
class below is a little elaborate: thebuild_class()
utility returns a class (a Lua table) given the constructor, destructor, and the class methods. Adjustments will no doubt be needed, but as a prototype demonstration the example should be OK.