Swig转换为派生类?

时间:2009-06-08 20:39:25

标签: lua type-conversion swig casting

我注意到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?)我有一个函数可以产生大约一百个可能的类中的一个,我想避免编写一个我必须在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成为知道的继承类的实例它是继承类的实例吗?

2 个答案:

答案 0 :(得分: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;
}

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

希望能帮助别人!

答案 1 :(得分:1)

我使用typemap和类字段解决了这个问题,该字段包含类类型的SWIG结构swig_type_info。

例如。假设您有一个包含基本链表功能的BaseClass,但实际节点可以是从BaseClass派生的任何类。因此,您有一个多态链接列表。在基类中,我定义了一个值" stored_swig_info"它保存了对SWIG_TypeQuery(..)的调用结果。我在初始化期间设置了这个值。然后在运行时 您可以使用以下内容:

// 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类型标签尚未填充。