我在将SWIG生成的Python包装器包装到C++类时遇到了一个奇怪的问题,其中当将std::map包装为std::shared_ptr类型时,我似乎无法使用标准的访问器函数ft。我设法产生了一个MWE,该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接口(interface)文件:

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

如所写,尝试使用 map 访问器时出现以下错误:
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 &

当我检查myTestMapstd::shared_ptr的类型时,它们都是各自类的%shared_ptr(TestMap)引用:
<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接口(interface)文件中省略了myTestMap声明并重新编译,则映射访问器(位于 test_interface.py 中)会很愉快。当我检查testMap*的类型时,它是:
<TestMap.testMap; proxy of <Swig Object of type 'testMap *' at 0x7f8eceb50630> >

因此,有两个问题:
  • 当我有一个SWIG对象指针引用(shared_ptr)时,为什么我的访问器调用正常工作,而在我有std::shared_ptr< testMap > *引用(例如shared_ptr)时却不能正常工作?
  • 鉴于我的派生 map 类型需要testMap*,如何解决此问题?

  • 奖励问题:,如果我声明存在std::shared_ptr<testMap>类型的shared_ptr类型(即使没有这样初始化),为什么SWIG会自动将testMap转换为ojit_code类型?

    最佳答案

    第一次myTestMap = tm.testMap()创建一个透明的shared_ptr。因此,myTestMap[1]是对shared_ptr的透明引用,并随后为键分配了值。
    第二次myTestMap = tm.testMap()创建空的std::map,因此myTestMap[1]是将值分配给 map 的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)创建一个完全透明的shared_ptr,并使用testMap默认构造函数对其进行初始化。

    关于python - SWIG:将std::map访问器与shared_ptr一起使用?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/45420243/

    10-11 17:06