1

このLuaコードは、テーブルを作成し、新しいメンバーを動的に追加します。これを実行すると"hello"、期待どおりに画面に表示されます。

foo = {}
foo.x = "hello"
print(foo.x)

しかし今、私はSWIGを使用していくつかのC++クラスをLuaにバインドしています。そのために、test.i(SWIGモジュールファイル)で次のような単純なクラスを作成しました。

%module test

%inline
%{

class Foo
{
public:
  Foo() { X = 0; }
  void SetX(int x) { X = x; }
  int GetX() { return X; }
private:
  int X;
};

%}

次に、次のようなテストLuaコードを作成しました。

obj = test.Foo()
obj:SetX(5)
print("Number: " .. obj:GetX())

期待どおりに実行および取得"Number 5"します。問題は、SWIGでバインドされたオブジェクトに新しいメンバーを動的に追加し、それにアクセスしようとすると、次のようになります。

obj.Y = 7
print("Number: " .. obj.Y)

このエラーメッセージが表示されます:

"attempt to concatenate field 'Y' (a nil value)"

SWIGを使用してバインドされたオブジェクトに新しいメンバーを動的に追加することは可能ですか?別のLuaバインディングライブラリに移動せずにオプションはありますか?

4

1 に答える 1

4

SWIGはオブジェクトにテーブルを使用しません。userdataを使用します。結局のところ、これらのオブジェクトはC ++オブジェクトであり、LuaコードがアクセスできないC++データを格納する必要があります。

そして、私は「別のLuaバインディングライブラリ」をわざわざ探す必要はありません。それらのほとんどすべてがuserdataを使用しますが、Luaコードは明示的に変更できません(これを正確に実行する機能を提供するため)。

しかし、それはあなたがカンニングできないという意味ではありません。

C ++コードから取得したオブジェクトは、いつでも独自のLuaテーブルにラップできます。このテーブルには、不明な呼び出しをC++オブジェクトに転送するメタテーブルがあります。そのためのコードは次のようになります。

local function WrapObject(cppObject)

    local proxy = {}

    local wrapper_metatable = {}

function wrapper_metatable.__index(self, key)
    local ret = rawget(self, key)
    if(not ret) then
        ret = cppObject[key]
        if(type(ret) == "function") then
            return function(self, ...)
                return ret(cppObject, ...)
            end
        else
            return ret
        end
    else
        return ret
    end

end


    setmetatable(proxy, wrapper_metatable)
    return proxy
end

返されるプロキシオブジェクトは、キーと値を設定できるLuaテーブルです。関数を呼び出すなどの値を取得すると、その値がテーブルに設定されているかどうかが確認されます。そうでない場合は、ラップしたC ++オブジェクトからフェッチしようとします。これによりメタテーブルが処理されます。

C ++クラスが、、など__addの他のメタ関数を使用する場合は、このメタテーブルを展開する必要があります。__sub__tostring

于 2012-11-10T22:14:20.723 に答える