SWIG:返回原始指针向量与共享指针
SWIG: Returning a vector of raw pointers vs. shared ptrs
我正在尝试为 C++ class 构建一个 python 接口,不幸的是,它混合了原始指针对象和共享指针对象/return 方法。本质上,对于这个接口,由于设计限制(即数据结构定义了一个降序层次结构,即 A -> B -> C,共享指针移动,我坚持使用 return 原始指针的某些函数向下,原始指针指向上方,以打破循环所有权。)
然而,我观察到的问题是,当我引入共享 ptr 模板时,即:
%shared_ptr(fooType)
然后 SWIG 知道为 fooType
包装/创建代理 classes,但不会为 fooType*
包装/创建代理。 (相反,如果我不包含 %shared_ptr
宏,SWIG 会为原始指针创建代理 classes。)
我的问题如下 - 我需要 return 原始指针对象的向量。例如,这是我的 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 为我的原始指针生成代理 class 和 同时共享我的指针,尤其是当我将它们包装到一个向量中时?
请注意,我不一定会看到使用 std::enabled_shared_from_this
之类的方法,因为我受困于 C++ 端的接口(即,我可以' 修改 class 以添加对 enable_shared_from_this
).
的继承
主要是,我想知道为什么当我启用共享指针时代理 class 生成会被破坏,以及我如何解决这个问题。 (我已经尝试开发我自己的类型映射来解析指针并将它们放回列表中,但这似乎没有帮助;我仍然以 SWIG 对象结束,我不能尊重它。)
最后,我无法确定一种合适的方法让 SWIG 在包装共享指针时为原始指针创建代理类型(即,我启用了 %shared_pointer(fooType)
宏) .
我最终采用的解决方法是通过 SWIG 中的包装器方法将原始指针克隆到新的共享指针对象中(从 this answer here 中获得一些灵感)。换句话说,使用带有 std::make_shared
的隐式复制构造函数 (fooType::fooType(fooType&)
) 创建一个新的 shared_ptr<fooType>
对象,该对象不会尝试声明原始原始指针的所有权(它不会t 控制;从而避免在删除共享指针并尝试释放其指针时进行双重删除。)
如果有人对如何为原始指针开发适当的类型映射有任何建议,以便让 SWIG 为两者创建代理 class(即允许我取消引用/调用方法原始指针对象以及共享指针),我当然很感兴趣;但与此同时,创建并行共享指针似乎是唯一可行的解决方法。
我正在尝试为 C++ class 构建一个 python 接口,不幸的是,它混合了原始指针对象和共享指针对象/return 方法。本质上,对于这个接口,由于设计限制(即数据结构定义了一个降序层次结构,即 A -> B -> C,共享指针移动,我坚持使用 return 原始指针的某些函数向下,原始指针指向上方,以打破循环所有权。)
然而,我观察到的问题是,当我引入共享 ptr 模板时,即:
%shared_ptr(fooType)
然后 SWIG 知道为 fooType
包装/创建代理 classes,但不会为 fooType*
包装/创建代理。 (相反,如果我不包含 %shared_ptr
宏,SWIG 会为原始指针创建代理 classes。)
我的问题如下 - 我需要 return 原始指针对象的向量。例如,这是我的 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 为我的原始指针生成代理 class 和 同时共享我的指针,尤其是当我将它们包装到一个向量中时?
请注意,我不一定会看到使用 std::enabled_shared_from_this
enable_shared_from_this
).
主要是,我想知道为什么当我启用共享指针时代理 class 生成会被破坏,以及我如何解决这个问题。 (我已经尝试开发我自己的类型映射来解析指针并将它们放回列表中,但这似乎没有帮助;我仍然以 SWIG 对象结束,我不能尊重它。)
最后,我无法确定一种合适的方法让 SWIG 在包装共享指针时为原始指针创建代理类型(即,我启用了 %shared_pointer(fooType)
宏) .
我最终采用的解决方法是通过 SWIG 中的包装器方法将原始指针克隆到新的共享指针对象中(从 this answer here 中获得一些灵感)。换句话说,使用带有 std::make_shared
的隐式复制构造函数 (fooType::fooType(fooType&)
) 创建一个新的 shared_ptr<fooType>
对象,该对象不会尝试声明原始原始指针的所有权(它不会t 控制;从而避免在删除共享指针并尝试释放其指针时进行双重删除。)
如果有人对如何为原始指针开发适当的类型映射有任何建议,以便让 SWIG 为两者创建代理 class(即允许我取消引用/调用方法原始指针对象以及共享指针),我当然很感兴趣;但与此同时,创建并行共享指针似乎是唯一可行的解决方法。