I have a BaseClass
and some derived classes
#ifndef TEST_H__
#define TEST_H__
#include <iostream>
#include <memory>
class BaseClass
{
public:
virtual double eval(double x) const = 0;
};
class Square: public BaseClass
{
public:
double eval(double x) const {return x*x;}
};
class Add1: public BaseClass
{
public:
Add1(BaseClass & obj): obj_(obj) {}
double eval(double x) const {return obj_.eval(x) + 1.0;}
private:
BaseClass & obj_;
};
#endif /* TEST_H__ */
which are treated with SWIG à la
%module test
%{
#define SWIG_FILE_WITH_INIT
%}
%{
#include "test.h"
%}
%include "test.h"
This can be used from Python like
import test
s = test.Square()
a = test.Add1(s)
print(a.eval(2.0))
What's segfaulting:
import test
a = test.Add1(test.Square())
print(a.eval(2.0))
Why? The test.Square()
is not assigned to a variable, so doesn't exist anymore after the assignment to a
, and obj_
points to invalid storage.
To avoid such behavior, the idea to to use std::shared_ptr<BaseClass>
instead of BaseClass&
, i.e.
class Add1: public BaseClass
{
public:
Add1(std::shared_ptr<BaseClass> & obj): obj_(obj) {}
double eval(double x) const {return obj_->eval(x) + 1.0;}
private:
std::shared_ptr<BaseClass> obj_;
};
This exact code won't work though with
TypeError: in method 'new_Add1', argument 1 of type 'std::shared_ptr< BaseClass > &'
Makes sense, too: test.Square()
doesn't return a std::shared_ptr<BaseClass>
but simply a Square
aka BaseClass
instance.
Is it possible to have test.Square()
return a shared pointer std::shared_ptr<Square>
?