代码之家  ›  专栏  ›  技术社区  ›  SuperElectric

如何从python SWIG包装器中向下转换c++对象?

  •  5
  • SuperElectric  · 技术社区  · 15 年前

    详情如下:

    我有两个c++类,基类和派生类。派生是基的一个子类。我有一个第三个类Container,它包含一个派生,并提供一个访问器。访问器将派生的作为常量基返回,如图所示:

    class Container {
      public:
        const Base& GetBase() const {
          return derived_;
        }
    
      private:
        Derived derived_;
    };
    

    %inline %{
      Derived* CastToDerived(Base* base) {
        return static_cast<Derived*>(base);
      }
    %}
    

    在我的python代码中,我调用了这个向下转换函数:

    base = container.GetBase()
    derived = CastToDerived(base)
    

    当我这样做时,我得到以下错误:

    TypeError: in method 'CastToDerived', argument 1 of type 'Base *'
    

    为什么会这样?

      Derived* CastToDerived(Base* base) {
        return static_cast<Derived*>(base);
      }
    
    //  (lots of other generated code omitted)
    
    SWIGINTERN PyObject *_wrap_CastToDerived(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
      PyObject *resultobj = 0;
      Base *arg1 = (Base *) 0 ;
      void *argp1 = 0 ;
      int res1 = 0 ;
      PyObject * obj0 = 0 ;
      Derived *result = 0 ;
    
      if (!PyArg_ParseTuple(args,(char *)"O:CastToDerived",&obj0)) SWIG_fail;
      res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_Base, 0 |  0 );
      if (!SWIG_IsOK(res1)) {
        SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "CastToDerived" "', argument " "1"" of type '" "Base *""'"); 
      }
      arg1 = reinterpret_cast< Base * >(argp1);
      result = (Derived *)CastToDerived(arg1);
      resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_Derived, 0 |  0 );
      return resultobj;
    fail:
      return NULL;
    }
    

    任何帮助都将不胜感激。

    --马特

    3 回复  |  直到 15 年前
        1
  •  3
  •   Chris Card    15 年前

    正如我上面所说的,这在swig 1.3.40中似乎可以正常工作。

    这是我的文件:

    c、 小时:

    #include <iostream>
    class Base {};
    class Derived : public Base
    {
        public:
            void f() const { std::cout << "In Derived::f()" << std::endl; }
    };
    class Container {
      public:
        const Base& GetBase() const {
          return derived_;
        }
      private:
        Derived derived_;
    };
    

    c、 我

    %module c
    
    %{
    #define SWIG_FILE_WITH_INIT
    #include "c.h"
    %}
    
    %inline %{
      Derived* CastToDerived(Base* base) {
        return static_cast<Derived*>(base);
      }
    %}
    class Base
    {
    };
    
    class Derived : public Base
    {
        public:
            void f() const;
    };
    
    class Container {
      public:
        const Base& GetBase() const;
    };
    

    ctest.py公司

    import c
    
    container = c.Container()
    b = container.GetBase()
    d = c.CastToDerived(b)
    d.f()
    print "ok"
    

    跑步:

    $ swig -c++ -python c.i
    $ g++ -fPIC -I/usr/include/python2.6 -c -g c_wrap.cxx
    $ g++ -shared -o _c.so c_wrap.o
    $ python ctest.py 
    In Derived::f()
    ok
    
        2
  •  0
  •   Vinzenz    15 年前

        3
  •  0
  •   PaulMcG    15 年前

    是否有可能多次定义基类?我在ctypes中也遇到过类似的问题,在两个不同的模块中无意中定义了相同的结构类。我在纯Python中也发生过类似的事情,我使用imp.load_模块加载了一个插件类,创建了该类的一个对象,然后重新加载了模块-poof!创建的对象将不再通过类的isinstance测试,因为重新加载的类,即使它具有相同的名称,也是具有不同id的不同类 this blog entry .)