【问题标题】:Swig typecast to derived class?Swig 类型转换为派生类?
【发布时间】:2010-11-01 07:12:47
【问题描述】:

我注意到 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 成为继承类的实例,知道它是继承类的实例?

【问题讨论】:

    标签: lua type-conversion swig casting


    【解决方案1】:

    我为我的问题制定了解决方案。我是 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;
    }
    

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

    希望对某人有所帮助!

    【讨论】:

    • 通常的 Lua 错误返回约定是返回 nil,即“消息”,您将返回数字代码和消息。返回 nil 很容易与 Lua 端的任何其他“有效”返回值区分开来,因此是成语。它也是许多核心模块遵循的模式。或者,您可以考虑使用 luaL_error() 代替,因为类型命名中的任何错误都可能是一个严重的问题。详情请见lua.org/manual/5.1/manual.html#luaL_error
    • 我没有发现任何泄漏,但我觉得自己对 SWIG 内部结构不够精通,无法证明这一点;-)
    【解决方案2】:

    我使用类型映射和包含类类型的 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 类型表尚未填充。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-10-14
      • 1970-01-01
      • 1970-01-01
      • 2011-04-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多