可以使用tolua ++將bar
函數導入到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函數返回一個userdata值。 Lua通過調用存儲在數據元表中的__gc
方法來取消分配這些用戶數據。給定一個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
使用用戶數據相同類型共享相同的元表的;因此每個類只應調用一次該函數(假設tolua ++的metatables只構造一次,並且只在退出時釋放)。
在這個答案的底部是一個完整的bar.pkg
文件導入bar
功能,並增加了一個bar
類名爲foo
一個Lua模塊。該foo
模塊加載到解釋器(see for example my SO tolua++ example)和像這樣使用:
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
$]
我目前想添加缺少的功能自己的,但是這意味着我會寫很多copypasta手工綁定代碼的,我想tolua ++做這項工作對我來說。我的另一種選擇是在tolua ++的內臟中徘徊,看看我是否可以利用現有的課程代碼。這兩種選擇都不是我覺得愉快的。 – Enno 2011-02-15 18:08:08