This question is in some ways an extension of the question posted here: SWIG_SHARED_PTR macro with templated class Although perhaps the issue is entirely unrelated.
The basic set up is this: I am trying to get SWIG to wrap a templated class as a shared_ptr. So 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 a lot of derived classes, this causes a lot of warnings in swig, and then build errors. These classes do not need to be handled as shared_ptr
's, so I would rather just ignore the warnings the above code generates. The solution to the error seems to be:
%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 is a huge mess, and I assume there must be some disadvantage to having everything represented as a shared_ptr (what is it?). Is there anyone around this?
EDIT: UPDATE WITH 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 this stripped down example, the swig call gives warnings, and the g++ call gives errors. Note that I've removed the templating, as it didn't seem to be an ingredient in the problem.
The errors are resolved by commenting out
%shared_ptr(Base)
The warning generated by swig is:
test.h:10: Warning 520: Derived class 'Derived' of 'Base' is not similarly marked as a smart pointer
and the error from g++ is:
test_wrap.cxx: In function ‘PyObject* _wrap_delete_Derived(PyObject*, PyObject*)’:
test_wrap.cxx:3155:22: error: ‘smartarg1’ was not declared in this scope
The warning here is because you need to tell SWIG about the whole class hierarchy, not just the base class in order to be able to usefully use a smart pointer. It needs to be able to convert between the smart pointers so that anything which takes a smart pointer to Base
can also accept one to Derived
. So your interface file needs to 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 problem that was warned about and generated code that compiled fine on my machine.
If you don't want to tell SWIG about all the derived types the simplest thing is to hide the type completely from SWIG - only ever expose the Base
type from things you want to wrap. You can do that in a few ways, the least intrusive being 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 causes only Base
to be wrapped, so the code that was failing to compile doesn't get generated any more.
Alternatively since that still requires a %ignore
per type you can modify the header file to hide the declaration/definition of Derived
from SWIG entirely:
class Base
{
int base_member;
};
#ifndef SWIG
class Derived : public Base
{
int derived_member;
};
#endif
If your project is organised such that there's one header file per type (roughly) you might be able to do this in a much simpler way by simply not using %include
with the files other than the base one.
If you still want to wrap them though, but not as a smart_ptr I think you're going to have to just accept that there will be a lot of %smart_ptr
- you could automate generating them though perhaps? You might be able to play games with modules, but I don't think that going to be easy or worth the effort.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With