Swig shared_ptr macro with template classes and derived classes

This question is in some ways a continuation of the question posted here: macro SWIG_SHARED_PTR with the template Although, perhaps, the problem is completely unrelated.

The basic setup is this: I'm trying to get SWIG to wrap a template class as shared_ptr. Thus, the interface file should look something like this.

%shared_ptr(template_instance) %include template_class.cpp %template(vector_instance) template_class<int>; 

Now the problem is that template_class has many derived classes, this causes a lot of warnings in swig and then generates errors. These classes should not be treated as shared_ptr , so I would rather just ignore the warnings that the code above generates. The solution to the error is as follows:

 %shared_ptr(template_derived1) %shared_ptr(template_derived2) . . . %shared_ptr(template_derivedn) %shared_ptr(template_instance) %include template_class.cpp %template(vector_instance) template_class<int>; 

This works, but it's a huge mess, and I suppose there must be some kind of flaw for everything to be presented as shared_ptr (what is it?). Anyone about this?

EDIT: UPDATE WITH A SPECIFIC EXAMPLE

test.h

 class Base { int base_member; }; class Derived : public Base { int derived_member; }; 

test.i

 %module test %{ #include "test.h" #include <boost/shared_ptr.hpp> %} %include <boost_shared_ptr.i> %shared_ptr(Base) %include test.h 

commands:

 swig -python -c++ test.i g++ -fPIC -I /usr/include/python2.7 -c test_wrap.cxx 

In the above example, a call to swig gives warnings, and a call to g ++ gives errors. Please note that I deleted the template as it did not seem to be an ingredient in the problem.

Errors are resolved by commenting.

 %shared_ptr(Base) 

Warning generated by swig:

 test.h:10: Warning 520: Derived class 'Derived' of 'Base' is not similarly marked as a smart pointer 

and error from g ++:

 test_wrap.cxx: In function 'PyObject* _wrap_delete_Derived(PyObject*, PyObject*)': test_wrap.cxx:3155:22: error: 'smartarg1' was not declared in this scope 
+4
source share
1 answer

The warning here is because you need to tell SWIG about the entire class hierarchy, not just the base class, in order to be able to use a smart pointer. It should be able to convert between smart pointers, so anything that accepts a smart pointer to Base can also take a single Derived value. Therefore, your interface file should be:

 %module test %{ #include "test.h" #include <boost/shared_ptr.hpp> %} %include <boost_shared_ptr.i> %shared_ptr(Base) %shared_ptr(Derived) %include "test.h" 

which resolved the issue that was warned about the generated code that was compiled on my machine.

If you don't want to tell SWIG about all derived types, the simplest thing is to completely hide the type from SWIG β€” just ever expose the Base type from the things you want to wrap. You can do this in several ways, the least intrusive, in order to change the interface file to:

 %module test %{ #include "test.h" #include <boost/shared_ptr.hpp> %} %include <boost_shared_ptr.i> %ignore Derived; %shared_ptr(Base) %include "test.h" 

This leads to the termination of only Base , so code that failed to compile is no longer generated.

Alternatively, since the type still requires %ignore , you can modify the header file to completely hide the Derived declaration / definition from SWIG:

 class Base { int base_member; }; #ifndef SWIG class Derived : public Base { int derived_member; }; #endif 

If your project is organized in such a way that there is one header file for each type (approximately), you can do it much easier simply by not using %include with files other than the base one.

If you still want to wrap them, but not like smart_ptr, I think you just have to accept that there will be a lot of %smart_ptr - could you automate their creation, perhaps perhaps? You may be able to play games with modules , but I don’t think it will be easy or worth the effort.

+4
source

All Articles