2

Swigは、オブジェクトを親クラスに型キャストできるようにするための関数のホスト全体を提供していることに気付きました。ただし、C ++では、次のような関数を生成できます。

A * getAnObject()
{
  if(someBoolean)
    return (A *) new B;
  else
    return (A *) new C;
}

ここで、「A」はクラス「B」と「C」の親です。次に、次のように都合のよいときに、返されたポインタを「B」タイプまたは「C」タイプに型キャストできます。

B * some_var = (B *) getAnObject();

実行時にジェネリックポインター生成関数から受け取ったオブジェクトを、ラッパーを使用してスクリプト言語で型キャストできる方法はありますか?(私の場合、Lua?)私は約100の可能なクラスの1つを生成できる関数を持っているので、C++で維持しなければならない巨大なスイッチ構造を記述したくありません。ジェネリックポインターを受け取った時点で、キャスト先のデータ型の文字列表現もあります。

何かご意見は?ありがとう!

- 編集 -

SWIGが、すべてのクラスのコピーコンストラクターを生成することを提案していることに気付きました。それらを生成させた場合、次のようなことを行うことができますか?:

var = myModule.getAnObject(); -- Function that returns an object type-cast down to a pointer of the parent class, as in the function getAnObject() above.
var = myModule.ClassThatExtendsBaseClass(var); -- A copy constructor that SWIG theoretically creates for me

そして、varは、継承クラスのインスタンスであることを認識している継承クラスのインスタンスになりますか?

4

2 に答える 2

2

私は自分の問題の解決策を開発しました。私は lua のガベージ コレクションを初めて使用するので、メモリ リーク防止機能があるかどうかはわかりませんが、必要なことは実行してくれます。(これも万能ではありません。有効なデータ型と、そのデータ型としてキャストしてはならないオブジェクトを渡すと、悪い結果が生じます。)

================================================== ===============================

static int lua_typecast_Object_I(lua_State *L)
{
        void * myDataPtr;
        void ** ptrToPtr = &myDataPtr;

        // Attempt to convert the first parameter to a pointer of
        // the lowest parent type from which all other data types 
        // inherit. e.g. "Object_I"

        if (!SWIG_IsOK(SWIG_ConvertPtr(L, 1, ptrToPtr, SWIGTYPE_p_Namespace1__Object_I, 0)))
        {
                lua_pushnumber(L, -1);
                lua_pushstring(L,"Pointer conversion in typecast function failed.");
                return 2;
        }

        const char * type_name = luaL_checkstring(L, 2);

        // Search the SWIG module for a swig_type_info that contains the data
        // type string that was passed as the second parameter

        swig_module_info* module=SWIG_GetModule(L);
        swig_type_info *type = SWIG_TypeQueryModule(module,module,type_name);
        if(type == NULL)
        {
                lua_pushnumber(L, -2);
                lua_pushstring(L,"Failed to find swig_type_info for specified type.");
                return 2;
        }

        // Using the swig_type_info that we found, create a new object on 
        // the stack of the desired data type and return.

        SWIG_Lua_NewPointerObj(L, myDataPtr, type, 0);
        return 1;
}

================================================== ===============================

それが誰かを助けることを願っています!

于 2009-06-18T17:40:32.937 に答える
1

typemap と、クラス型の SWIG 構造体 swig_type_info を保持するクラス フィールドを使用して、これを解決しました。

例えば。基本的なリンク リスト機能を含む BaseClass があるとしますが、実際のノードは BaseClass から派生した任意のクラスにすることができます。したがって、多態的な連結リストがあります。基本クラスでは、SWIG_TypeQuery(..) への呼び出しの結果を保持する値「stored_swig_info」を定義します。初期化中にこの値を設定しました。次に、実行時に以下を使用できます。

// The typemap converts a function result from C->Lua. 
%typemap(out) BaseClass* {
   // stored_swig_info is set by calling SWIG_TypeQuery("DerivedClass *"), done at
   // initialization, so it can be used here to read the actual type
   swig_type_info* info = $1->stored_swig_info;
   SWIG_NewPointerObj(L, $1, info, 0); SWIG_arg++;
};

// base class
class BaseClass {
private:
  swig_type_info *stored_swig_info;
public:
  BaseClass* next () { ... };
  BaseClass* prev () { ... };
};

// derived class
class DerivedClass: public BaseClass {
};

実際のクラス モジュールでは、コンストラクターは次のことを行います。

BaseClass::BaseClass () {
  ...
  stored_swig_info = SWIG_TypeQuery("BaseClass *");
  ...
}

...

DerivedClass::DerivedClass () {
  ...
  stored_swig_info = SWIG_TypeQuery("DerivedClass *");
  ...
}

実装上の注意。lua モジュールが初期化された後にこの初期化が呼び出されることを確認してください。そうしないと、SWIG タイプテーブルがまだ入力されていません。

于 2014-09-10T18:59:32.343 に答える