这些bar
函数可以使用 tolua++ 导入 Lua 并包装以产生对象样式的接口,包括垃圾收集。
为了演示参数的传递,我将bar
接口更改为
bar * bar_create(int x);
int bar_do_something(bar * baz, int y);
void bar_free(bar * baz);
并编写了一个测试实现,在调用函数时打印出x
,y
等。
bar_create()
Lua 函数返回一个用户数据值。__gc
Lua 通过调用存储在数据元表中的方法来释放这些用户数据。给定一个userdata
值和一个析构函数gc
,该__gc
方法被覆盖,这样它首先调用gc
然后调用原始gc
方法:
function wrap_garbage_collector(userdata, gc)
local mt = getmetatable(userdata)
local old_gc = mt.__gc
function mt.__gc (data)
gc(data)
old_gc(data)
end
end
相同类型的用户数据共享相同的元表;因此该wrap_garbage_collector()
函数应该为每个类只调用一次(假设 tolua++ 的元表只构造一次并且只在退出时释放)。
这个答案的底部是一个完整的bar.pkg
文件,它导入bar
函数并将一个bar
类添加到名为foo
. 该foo
模块被加载到解释器中(例如参见我的 SO tolua++ 示例)并像这样使用:
bars = {}
for i = 1, 3 do
bars[i] = foo.bar(i)
end
for i = 1, 3 do
local result = bars[i]:do_something(i * i)
print("result:", result)
end
测试实现打印出发生了什么:
bar(1)
bar(2)
bar(3)
bar(1)::do_something(1)
result: 1
bar(2)::do_something(4)
result: 8
bar(3)::do_something(9)
result: 27
~bar(3)
~bar(2)
~bar(1)
下面的类的构造bar
有点复杂:build_class()
实用程序返回一个给定构造函数、析构函数和类方法的类(Lua 表)。毫无疑问,需要进行调整,但作为原型演示,该示例应该没问题。
$#include "bar.hpp"
// The bar class functions.
bar * bar_create(int x);
int bar_do_something(bar * baz, int y);
void bar_free(bar * baz);
$[
-- Wrapping of the garbage collector of a user data value.
function wrap_garbage_collector(userdata, gc)
local mt = getmetatable(userdata)
local old_gc = mt.__gc
function mt.__gc (data)
gc(data)
old_gc(data)
end
end
-- Construction of a class.
--
-- Arguments:
--
-- cons : constructor of the user data
-- gc : destructor of the user data
-- methods : a table of pairs { method = method_fun }
--
-- Every 'method_fun' of 'methods' is passed the user data
-- as the first argument.
--
function build_class(cons, gc, methods)
local is_wrapped = false
function class (args)
-- Call the constructor.
local value = cons(args)
-- Adjust the garbage collector of the class (once only).
if not is_wrapped then
wrap_garbage_collector(value, gc)
is_wrapped = true
end
-- Return a table with the methods added.
local t = {}
for name, method in pairs(methods) do
t[name] =
function (self, ...)
-- Pass data and arguments to the method.
return (method(value, ...))
end
end
return t
end
return class
end
-- The Lua module that contains our classes.
foo = foo or {}
-- Build and assign the classes.
foo.bar =
build_class(bar_create, bar_free,
{ do_something = bar_do_something })
-- Clear global functions that shouldn't be visible.
bar_create = nil
bar_free = nil
bar_do_something = nil
$]