SWIG:返回原始指针与共享ptrs

时间:2017-11-09 16:40:47

标签: python c++ pointers swig

我试图构建一个我所拥有的C ++类的python接口,遗憾的是它包含原始和共享指针对象/返回方法的混合。本质上,通过这个接口,由于设计约束,我坚持使用返回原始指针的某些函数(即,数据结构定义了一个降序层次结构,即A - > B - > C,共享指针移动向下,以及指向备份的原始指针,以打破循环所有权。)

我观察到的问题是,当我引入共享的ptr模板时,即:

%shared_ptr(fooType)

然后SWIG知道为fooType包装/创建代理类,但不是fooType*。 (相反,如果我不包含%shared_ptr宏,SWIG会为原始指针创建代理类。)

我的问题发生如下 - 我需要返回一个原始指针对象的向量。例如,这是我的MWE:

fooType.h

#include <iostream>
#include <vector>

class fooType{
  public:
  fooType() { };
  ~fooType() { };
  void printFoo() { std::cerr << "FOO!" << std::endl; }
  static std::shared_ptr<fooType> make_shared() { 
      return std::shared_ptr<fooType>(new fooType()); 
  }
  static fooType* newPtr() { return new fooType(); }
  static std::vector<fooType*> newVecPtr() {
      std::vector<fooType*> retVec;
      for( size_t i = 0; i < 3; ++i) { retVec.push_back(new fooType()); }
     return retVec;
  }
};

fooType.i

%module fooType

%include <std_map.i>
%include <std_shared_ptr.i>
%include <std_vector.i>

%{
#include "fooType.h"
%}

%shared_ptr(fooType);
%include "fooType.h"

%template(fooVec) std::vector<fooType>;
%template(fooPtrVec) std::vector<fooType*>;

testFooType.py

import fooType as fooMod

ft = fooMod.fooType.make_shared()
ftPtr = fooMod.fooType.newPtr()
fooVec = fooMod.fooType.newVecPtr()

print(ftPtr)
print(ft)
print(fooVec)

for foo in fooVec:
   print(foo)
   foo.printFoo()

这给了我:

<fooType.fooType; proxy of <Swig Object of type 'std::shared_ptr< fooType > *' at 0x7fd83ccfeb10> >
<fooType.fooType; proxy of <Swig Object of type 'std::shared_ptr< fooType > *' at 0x7fd83ccfec30> >
<fooType.fooPtrVec; proxy of <Swig Object of type 'std::vector< fooType * > *' at 0x7fd83ccfeba0> >
<Swig Object of type 'fooType *' at 0x7fd834c1dba0>
Traceback (most recent call last):
  File "testFooType.py", line 13, in <module>
    foo.printFoo()
AttributeError: 'SwigPyObject' object has no attribute 'printFoo'

如果我注释掉%shared_ptr(fooType)宏,我会得到:

<fooType.fooType; proxy of <Swig Object of type 'std::vector< fooType * >::value_type' at 0x7feab54b42a0> >
<fooType.fooTypePtr; proxy of <Swig Object of type 'std::shared_ptr< fooType > *' at 0x7feab54b4240> >
<fooType.fooPtrVec; proxy of <Swig Object of type 'std::vector< fooType * > *' at 0x7feab54b4210> >
<fooType.fooType; proxy of <Swig Object of type 'std::vector< fooType * >::value_type' at 0x7feab54b4780> >
FOO!
<fooType.fooType; proxy of <Swig Object of type 'std::vector< fooType * >::value_type' at 0x7feab54b4c90> >
FOO!
<fooType.fooType; proxy of <Swig Object of type 'std::vector< fooType * >::value_type' at 0x7feab54b4780> >
FOO!

那么,我在这里做错了什么?换句话说,我怎样才能让SWIG同时为我的原始指针我的共享指针生成一个代理类,特别是当我将它们包装成矢量时?

请注意,我不一定会看到使用类似std::enabled_shared_from_this as illustrated here之类的方法,也就是因为我在C ++方面遇到了我的界面(即,我无法修改类以添加enable_shared_from_this)的继承。

大多数情况下,我想知道为什么代理类生成在我启用共享指针时会被破坏,以及我如何解决这个问题。 (我已经尝试开发自己的类型映射来解析指针并将它们放回列表中,但这似乎没有帮助;我仍然最终得到了SWIG对象,我无法做到这一点顺从。)

1 个答案:

答案 0 :(得分:0)

最后,当共享指针被包装时,我无法确定让SWIG为原始指针创建代理类型的合适方法(即,我启用了%shared_pointer(fooType)宏) 。

我最终得到的解决方法是通过SWIG中的包装器方法将原始指针克隆到新的共享指针对象中(从this answer here获取一些灵感)。换句话说,使用隐式复制构造函数(fooType::fooType(fooType&))和std::make_shared来创建一个新的shared_ptr<fooType>对象,它不会尝试声明原始指针的所有权(它是不控制;因此在删除共享指针时避免双重删除并尝试释放其指针。)

如果有人对如何为原始指针开发适当的类型映射有任何建议,以获得SWIG为两者创建代理类(即,允许我在原始指针对象上取消引用/调用方法以及共享指针),我当然感兴趣;但与此同时,似乎创建一个并行共享指针是唯一可行的解​​决方法。