I had a strange problem with a SWIG-generated Python shell for a C ++ class, in which I cannot use the standard std::map access functions when it is wrapped as a std::shared_ptr . I managed to create an MWE that reproduces the odd behavior that I am observing.
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; } };
And then my SWIG interface file:
TestMap.i
%module TestMap %include <std_map.i> %include <std_shared_ptr.i> %{
Finally, the script test that I use to test the interface:
test_interface.py
import TestMap as tm ft = tm.fooType.make_shared() myTestMap = tm.testMap() myTestMap[1] = ft
As written, I get the following error when trying to use a card accessory:
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 &
When I check the type of ft and myTestMap , both are std::shared_ptr references to their respective classes:
<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> >
Now for the odd part - if I omitted the %shared_ptr(TestMap) from my SWIG interface file and recompiled, the map accessory happily works for it (in test_interface.py ). When I check the myTestMap type, this is:
<TestMap.testMap; proxy of <Swig Object of type 'testMap *' at 0x7f8eceb50630> >
So, two questions:
- Why does my access request work correctly when I have a reference to a pointer to a SWIG object (
testMap* ), but not when I have a shared_ptr link (for example, std::shared_ptr< testMap > * )? - How do I get around this, given that I need
shared_ptr for my derived map type?
Bonus question: why does SWIG automatically convert testMap* to type std::shared_ptr<testMap> if I declare the existence of shared_ptr for type testMap (even if it is not initialized as such?)