SWIG:使用带有shared_ptr的std :: map访问器?

Pro*_*uke 6 c++ python swig

我遇到了一个SWIG生成的C++类包装器的奇怪问题,其中我似乎无法使用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; }
};
Run Code Online (Sandbox Code Playgroud)

然后是我的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"
Run Code Online (Sandbox Code Playgroud)

最后,我用来测试界面的测试脚本:

test_interface.py

import TestMap as tm

ft = tm.fooType.make_shared()
myTestMap = tm.testMap()

myTestMap[1] = ft
Run Code Online (Sandbox Code Playgroud)

写入时,我尝试使用地图访问器时出现以下错误:

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 &
Run Code Online (Sandbox Code Playgroud)

当我检查的类型ftmyTestMap,两者都是std::shared_ptr各自类的引用:

<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> >
Run Code Online (Sandbox Code Playgroud)

现在对于奇怪的部分 - 如果我%shared_ptr(TestMap)从SWIG接口文件中省略声明并重新编译,则地图访问器(在test_interface.py中)很高兴.当我检查类型时myTestMap,它是:

<TestMap.testMap; proxy of <Swig Object of type 'testMap *' at 0x7f8eceb50630> >
Run Code Online (Sandbox Code Playgroud)

那么,有两个问题:

  1. 当我有SWIG对象指针引用(testMap*)时,为什么我的访问器调用正常工作,但是当我有shared_ptr引用时(例如,std::shared_ptr< testMap > *)?
  2. 我如何解决这个问题,因为我需要一个shared_ptr我的派生地图类型?

额外的问题:为什么如果我声明类型的存在类型,SWIG会自动转换testMap*为类型(即使它没有被初始化?)std::shared_ptr<testMap>shared_ptrtestMap

lua*_*art 1

第一次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(请参阅默认构造函数),因此testMapPtr[1]会取消引用NULL值,从而产生一些异常。
更新: %shared_ptr(testMap)创建一个完全透明的shared_ptr,并使用testMap默认构造函数进行初始化。