2

現在、C++ オブジェクトをインスタンス化し、Lua で SWIG バインディングを使用して渡す方法を知っています。必要なのはその逆です。

Lua & C++ & SWIG を使用しています。

私は C++ のインターフェースと lua のオブジェクトを持っています。これらは同じ仕事をし、同じ構造を持つメソッドを実装しています。これらのオブジェクトを lua でインスタンス化できるようにしたいのですが、似ているインターフェイスへのポインターを使用して C++ で渡すことができます。

そのため、上記の lua オブジェクトのハンドラーとして機能するインターフェイスの C++ 実装を作成することは想像できますが、これを行う方法はわかりません。このクラスは、C++ の世界で lua オブジェクトの代表またはプロキシとして機能します。

明確にするために、私が尋ねた同様の質問への回答で使用されている次のコード例から始めます。

C++ コード:

// Represents a generic bank account
class Account {
    virtual void deposit(double amount) = 0;
};

ルアコード:

SavingsAccount = { balance = 0 }
SavingsAccount.deposit = function(amount)
    SavingsAccount.balance = SavingsAccount.balance + amount
end

-- Usage
a = SavingsAccount
a.balance = 100
a.deposit(1000)

ここで、Bank という C++ のクラスがあるとします。

class Bank {
    void AddAccount(Account* a);
};

ここで欲しいのは、lua で次のことを行うためのメカニズムです。

SavingsAccount = { balance = 0 }
SavingsAccount.deposit = function(amount)
    SavingsAccount.balance = SavingsAccount.balance + amount
end

-- Usage
a = SavingsAccount
bank:AddAccount(a)

プロキシとして機能する C++ クラスをインスタンス化し、すべての lua 関数を含む lua テーブルに渡すなど、追加の手順を実行する必要がある場合は、次のようになると想像できます。

C++ コード:

// Represents a generic bank account
class ProxyAccount : public Account {
    virtual void deposit(double amount);
};

ルアコード:

SavingsAccount = { balance = 0 }
SavingsAccount.deposit = function(amount)
    SavingsAccount.balance = SavingsAccount.balance + amount
end

-- Usage
a = SavingsAccount
a.balance = 100
a.deposit(1000)

proxy = program.ProxyAccount()
proxy.settable(a)
bank:AddAccount(p)

ここでの問題は、ProxyAccount クラスをどのように実装するか、または settable の関数シグネチャがどのように見えるかさえわからないことです...

4

3 に答える 3

2

あなたの例と議論から私が収集しているように見えるのは、Lua が主要言語であり、C++ がクライアントであると期待しているということです。問題は、Lua C インターフェイスがそのように動作するように設計されていないことです。Lua はクライアントとして機能するように設計されており、すべてのハードワークは C で記述されているため、Lua は簡単に呼び出すことができます。

ここで重要な問題は、オブジェクトを C で表現したくないのに、それを Lua で表現したいのはなぜかということです。C++ ははるかに低レベルの言語であり、オブジェクト定義は静的でなければならず、Lua はその「オブジェクト」を動的に定義するため、Lua を C++ オブジェクトに適応させるのははるかに簡単です。

私が目にするもう 1 つの問題は、非常にオブジェクト指向の方法で Lua コードを設計しているように見えることです。Lua はオブジェクト指向の概念を偽造できますが、オブジェクト指向言語として構築されているわけではなく、主にオブジェクト指向言語として使用するべきではないことに注意してください。完全な OO スクリプト言語が必要な場合は、代わりに python を使用してください。

本当に別の方法でやりたいと思っていて、他の方法がうまくいかない場合は、Lua オブジェクトをコルーチンとして保持することをお勧めします。これにより、次のことが可能になります。

  • オブジェクトの表現を C++ で保持する (lua_State *)
  • 同じ「オブジェクト タイプ」の複数の個別のインスタンスを持つ
  • Lua がクリーンアップを処理します

ただし、欠点は次のとおりです。

  • 「オブジェクト」に作用するすべての関数は、lua API を介して行う必要があります。
  • さまざまな lua タイプを簡単かつ迅速に認識する方法はありません (メタテーブルを使用できます)。
  • 実装は非常に面倒で、解読が困難です。

編集: スクリプト内のオブジェクトへのインターフェイスを公開する方法は次のとおりです。各オブジェクトインスタンスは新しいlua_Stateを実行し、そのスクリプトを個別に実行するため、「オブジェクトメンバーデータ」をスクリプトインスタンス内のグローバルにすることができます. オブジェクトのメソッドの API を実装すると、次のようになります。

int move(lua_State * L)
{
  int idx = lua_getglobal(L, "this");
  assert(!lua_isnull(-1));
  AIObject * obj = static_cast<AIObject *>(lua_touserdata(L, -1));
  lua_pop(1);
  //Pop the other parameters
  obj->move(/*params*/);
}
于 2009-12-30T09:53:01.283 に答える
1

必要な C 関数を Lua にバインドして、そこから呼び出すことができます。この関数で、スクリプトと C++ コードの間のコントラクトを定義できます。たとえば、次のようにすると、必要なことが実行されます。さまざまな Lua オブジェクト タイプを区別できるように、Lua テーブルにメタ テーブル情報を追加する必要があります。

int lua_AddBankAccount(lua_State* L, int pos)
{
    // Assume you've created metadata for your Lua objects.
    if (IsAccount(L, pos))
    {
       // process your 'Account' Lua instance.
    }
    else
    {
       // error - tried to add a non-Account.
    }
}

これを SWIG でさらに進めて、任意の C メソッドをバインドできますが、基本的には同じです。

于 2009-11-24T21:54:54.117 に答える