2012-02-26 21 views
2

SWIGでいくつかのC++クラスをLuaにエクスポートしています。今、私はブーストを取るべきであるのluaスクリプト内で宣言された関数を呼び出したいSWIG:Lua - Lua関数のパラメータとしてC++インスタンスを渡す

namespace boost 
{ 
    namespace filesystem 
    { 
     class path {}; 
    } 
} 

::ファイルシステムを::パス&として:私はこのようなSWIGインタフェースファイルにブースト::ファイルシステム::パスを宣言しましたパラメータを別のオブジェクトに渡します。私はオブジェクトにパスを渡すことができる必要があります。パスオブジェクトから機能を使用する必要はありません。

function on_path_selected(the_path) 
    another_object:set_path(the_path) 
end 

私はそのインデックスを使ってC++からLua関数を呼び出す予定です。

質問:boost :: filesystem :: pathをパラメータとしてLua関数にプッシュするにはどうすればよいですか?

答えて

5

これは実際にはかなり複雑です。 SWIGの予想される使用法は、Lua用のモジュールを作成することです。 Luaスクリプトは、何が呼び出され、何が呼び出されないのかを決定するものでなければなりません。 SWIGを使っていくつかのC++オブジェクトを公開してからアプリケーションから直接Luaコードを呼び出す組み込み用途のためのものではありません。

これは不可能だと言っているのではなく、複雑です。

すべてのSWIGベースのC++オブジェクトは、Luaを介してポインタとして渡されます。したがって、所有権は問題です。スタックオブジェクトへのポインタをLuaに押し込むことはできません。

これを行う最も安全な方法は、オブジェクトの新しいコピーをLuaに渡すことです。そうすれば、Luaはポインタを所有します。 SWIGはLuaがポインタを所有していることを知り、適切なガベージコレクションメカニズムを付けてそれをクリーンアップします。だから、すべてのメモリが賢明でなければならない。

これを行うには、適切な "ボクシング"(より良い用語が必要なため)SWIGが望んでいるようにそのオブジェクトが必要です。これには、特定のSWIGマクロを使用する必要があります。あなたはSWIGにpathタイプをバインドしているか、あなたがスタックLuaの上にそれを固執するこのような何かをするだろう考える

swig_type_info *pathType = SWIG_TypeQuery("boost::filesystem::path *"); 
boost::filesystem::path *pArg = new boost::filesystem::path(the_path); 
SWIG_NewPointerObj(L, pArg, outputType, 1); 

SWIG_TypeQueryがにSWIGに拘束されている任意のオブジェクトの種類をフェッチルアこの型情報オブジェクトは、SWIG_NewPointerObjに必要であり、その型へのポインタをとります。どちらもマクロです。 SWIG_NewPointerObjはポインタのLuaの所有権を与えます。 Luaのガベージコレクタは、SWIGのメタテーブルのおかげでそれを削除します。また、SWIG_NewPointerObjは、オブジェクトをlua_Stateスタックにプッシュします。

スタックに入ったら、それを使って何でもできます。それを関数からLuaに返し、それを引数としてLua関数に渡し、グローバル変数にスティックします。これはLuaの値です。

このコードをプロジェクトに入力すると、コンパイラがswig_type_infoと表示されたときにコンパイルエラーが発生する可能性があります。このタイプは、SWIGのコマンドラインで生成されたソースファイル内でと内部的にはと定義されています。

は、2つのオプションがあります。.swigファイル自体にこのソースコードを入れ

  1. 。はい、そうです。通常のC++関数を逐語的なセクション内に定義することができます(%{%}区切りブロック)。これらの関数はSWIGの生成コードに直接コピーされます。プロトタイプをヘッダーに入れてアクセスできます。これは最も簡単で簡単な作業方法です。これは、既存のC++関数がLua APIに適切でない(または単に存在しない)特殊なインタフェースを作成するためによく使用されます。

  2. これらの定義を含む適切なヘッダーを生成するには、-external-runtime引数を使用します。これは、.cppファイルを生成するステップとは異なるSWIG実行ステップでなければなりません。実際、SWIGファイルなどは実際には処理されません。必要なのは、ターゲット言語(-lua)と、C++(-c++)を使用しているかどうかです。swig -c++ -lua -external-runtime someheader.hのコマンドがあるだけで、タイプとマクロを取得するだけです。

    はあなたがLuaのにSWIG-バインドされたオブジェクトを添付したいどんなソースでそのヘッダをインクルードします。

+0

この偉大な答えをいただき、ありがとうございます。私は現在、生成されたSWIG cppソースファイルを掘り下げており、あなたが記述したものの正確さのレベルを十分に理解することができます。はい、それはこれを働かせるエレガントな方法を見つけるための長い道のりになると思われます。 ありがとうございます! 編集:これを行うボタンが表示されるとすぐにこれを回答としてマークします。 – damian

関連する問題