SWIG:将 std::map 访问器与 shared_ptr 一起使用?
SWIG: Using std::map accessors with a shared_ptr?
我在使用 SWIG 生成的 Python 包装器到 C++ class 时遇到了一个奇怪的问题,其中我似乎无法使用 std::map
的标准访问器函数包装为 std::shared_ptr
类型。我设法制作了一个重现我观察到的奇怪行为的 MWE。
TestMap.h
#include <iostream>
#include <map>
#include <memory>
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());
}
};
class testMap : public std::map<int, std::shared_ptr<fooType> > {
public:
void printBar() { std::cerr << "bar." << std::endl; }
};
然后是我的SWIG接口文件:
TestMap.i
%module TestMap
%include <std_map.i>
%include <std_shared_ptr.i>
%{
#include "TestMap.h"
%}
%shared_ptr(fooType);
%shared_ptr(testMap);
%shared_ptr(std::map<int, std::shared_ptr<fooType> > );
%template(fooMap) std::map< int, std::shared_ptr<fooType> >;
%include "TestMap.h"
最后,我用来测试界面的测试脚本:
test_interface.py
import TestMap as tm
ft = tm.fooType.make_shared()
myTestMap = tm.testMap()
myTestMap[1] = ft
如前所述,当我尝试使用地图访问器时出现以下错误:
Traceback (most recent call last):
File "test_interface.py", line 9, in <module>
myTestMap[1] = ft
File "/home/sskutnik/tstSWIG/TestMap.py", line 217, in __setitem__
return _TestMap.fooMap___setitem__(self, *args)
NotImplementedError: Wrong number or type of arguments for overloaded function 'fooMap___setitem__'.
Possible C/C++ prototypes are:
std::map< int,std::shared_ptr< fooType > >::__setitem__(std::map< int,std::shared_ptr< fooType > >::key_type const &)
std::map< int,std::shared_ptr< fooType > >::__setitem__(std::map< int,std::shared_ptr< fooType > >::key_type const &,std::map< int,std::shared_ptr< fooType > >::mapped_type const &
当我检查 ft
和 myTestMap
的类型时,它们都是 std::shared_ptr
对它们各自 class 的引用:
<TestMap.fooType; proxy of <Swig Object of type 'std::shared_ptr< fooType > *' at 0x7fa812e80a80> >
<TestMap.testMap; proxy of <Swig Object of type 'std::shared_ptr< testMap > *' at 0x7fa812e80c90> >
现在奇怪的部分 - 如果我从我的 SWIG 接口文件中省略 %shared_ptr(TestMap)
声明并重新编译,地图访问器(在 test_interface.py 中)愉快地工作。当我检查 myTestMap
的类型时,它是:
<TestMap.testMap; proxy of <Swig Object of type 'testMap *' at 0x7f8eceb50630> >
那么,两个问题:
- 为什么我的访问器调用在我有 SWIG 对象指针引用 (
testMap*
) 时可以正常工作,但在我有 shared_ptr
引用(例如 std::shared_ptr< testMap > *
)时却不能?
- 鉴于我的派生地图类型需要
shared_ptr
,我该如何解决这个问题?
奖金问题:如果我声明存在 shared_ptr
类型,为什么 SWIG 会自动将 testMap*
转换为 std::shared_ptr<testMap>
类型testMap
类型(即使它没有这样初始化?)
第一次 myTestMap = tm.testMap()
创建透明 shared_ptr。所以 myTestMap[1]
是 shared_ptr 的透明取消引用,随后将值分配给键。
第二次 myTestMap = tm.testMap()
创建空 std::map,所以 myTestMap[1]
是给地图的 key=1
赋值。
%shared_ptr(testMap)
在语义上类似于 %template(testMap) shared_ptr<testMap>
。 %template(testMapPtr) shared_ptr<testMap>
将创建一个新的 shared_ptr 类型 testMapPtr
,它最初持有 NULL(请参阅 default constructor),因此 testMapPtr[1]
将取消引用 NULL 值,从而产生一些异常。
更新: %shared_ptr(testMap)
创建一个使用 testMap 默认构造函数初始化的完全透明 shared_ptr。
我在使用 SWIG 生成的 Python 包装器到 C++ class 时遇到了一个奇怪的问题,其中我似乎无法使用 std::map
的标准访问器函数包装为 std::shared_ptr
类型。我设法制作了一个重现我观察到的奇怪行为的 MWE。
TestMap.h
#include <iostream>
#include <map>
#include <memory>
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());
}
};
class testMap : public std::map<int, std::shared_ptr<fooType> > {
public:
void printBar() { std::cerr << "bar." << std::endl; }
};
然后是我的SWIG接口文件:
TestMap.i
%module TestMap
%include <std_map.i>
%include <std_shared_ptr.i>
%{
#include "TestMap.h"
%}
%shared_ptr(fooType);
%shared_ptr(testMap);
%shared_ptr(std::map<int, std::shared_ptr<fooType> > );
%template(fooMap) std::map< int, std::shared_ptr<fooType> >;
%include "TestMap.h"
最后,我用来测试界面的测试脚本:
test_interface.py
import TestMap as tm
ft = tm.fooType.make_shared()
myTestMap = tm.testMap()
myTestMap[1] = ft
如前所述,当我尝试使用地图访问器时出现以下错误:
Traceback (most recent call last):
File "test_interface.py", line 9, in <module>
myTestMap[1] = ft
File "/home/sskutnik/tstSWIG/TestMap.py", line 217, in __setitem__
return _TestMap.fooMap___setitem__(self, *args)
NotImplementedError: Wrong number or type of arguments for overloaded function 'fooMap___setitem__'.
Possible C/C++ prototypes are:
std::map< int,std::shared_ptr< fooType > >::__setitem__(std::map< int,std::shared_ptr< fooType > >::key_type const &)
std::map< int,std::shared_ptr< fooType > >::__setitem__(std::map< int,std::shared_ptr< fooType > >::key_type const &,std::map< int,std::shared_ptr< fooType > >::mapped_type const &
当我检查 ft
和 myTestMap
的类型时,它们都是 std::shared_ptr
对它们各自 class 的引用:
<TestMap.fooType; proxy of <Swig Object of type 'std::shared_ptr< fooType > *' at 0x7fa812e80a80> >
<TestMap.testMap; proxy of <Swig Object of type 'std::shared_ptr< testMap > *' at 0x7fa812e80c90> >
现在奇怪的部分 - 如果我从我的 SWIG 接口文件中省略 %shared_ptr(TestMap)
声明并重新编译,地图访问器(在 test_interface.py 中)愉快地工作。当我检查 myTestMap
的类型时,它是:
<TestMap.testMap; proxy of <Swig Object of type 'testMap *' at 0x7f8eceb50630> >
那么,两个问题:
- 为什么我的访问器调用在我有 SWIG 对象指针引用 (
testMap*
) 时可以正常工作,但在我有shared_ptr
引用(例如std::shared_ptr< testMap > *
)时却不能? - 鉴于我的派生地图类型需要
shared_ptr
,我该如何解决这个问题?
奖金问题:如果我声明存在 shared_ptr
类型,为什么 SWIG 会自动将 testMap*
转换为 std::shared_ptr<testMap>
类型testMap
类型(即使它没有这样初始化?)
第一次 myTestMap = tm.testMap()
创建透明 shared_ptr。所以 myTestMap[1]
是 shared_ptr 的透明取消引用,随后将值分配给键。
第二次 myTestMap = tm.testMap()
创建空 std::map,所以 myTestMap[1]
是给地图的 key=1
赋值。
%shared_ptr(testMap)
在语义上类似于 %template(testMap) shared_ptr<testMap>
。 %template(testMapPtr) shared_ptr<testMap>
将创建一个新的 shared_ptr 类型 testMapPtr
,它最初持有 NULL(请参阅 default constructor),因此 testMapPtr[1]
将取消引用 NULL 值,从而产生一些异常。
更新: %shared_ptr(testMap)
创建一个使用 testMap 默认构造函数初始化的完全透明 shared_ptr。