関数は、bar
tolua ++を使用してLuaにインポートし、ラップして、ガベージコレクションを含むオブジェクトスタイルのインターフェイスを生成できます。
引数の受け渡しを示すために、bar
インターフェイスを次のように変更しました
bar * bar_create(int x);
int bar_do_something(bar * baz, int y);
void bar_free(bar * baz);
関数が呼び出されたときに、などx
を出力するテスト実装を作成しました。y
Lua関数はbar_create()
userdata値を返します。__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()
関数はクラスごとに1回だけ呼び出す必要があります(tolua ++のメタテーブルが1回作成され、終了時にのみ割り当て解除されると仮定します)。
この回答の下部には、関数をインポートし、という名前のLuaモジュールにクラスを追加する完全なbar.pkg
ファイルがあります。モジュールはインタープリターにロードされ(たとえば、私のSO tolua ++の例を参照)、次のように使用されます。bar
bar
foo
foo
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
$]