Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to make interface for std::pair<> with no default constructor in swig & python?

Tags:

c++

python

swig

I'm going to make python wrapper using swig. I have some classes and types in c++ dll.

class Image
{
public:
    Image(const Image&);
    Image& operator= (const Image&);
    ~Image();

    unsigned int width() const;
    unsigned int height() const;
};
struct Property
{
    std::string path;
    std::string datetime;
};
typedef std::pair<Image, Property> MyImage;
class Manage
{
public:
    Manage();
    ~Manage();
    void addMyImage(MyImage img);
    MyImage getMyImage(int index);
};

I made swig interface file following this:

%include "std_pair.i"
%template(MyImage) std::pair<Image, Property>;
class Image
{
public:
    Image(const Image&);
    ~Image();

    unsigned int width() const;
    unsigned int height() const;
};
class Manage
{
public:
    Manage();
    ~Manage();

    void addMyImage(std::pair<Image, Property> img);
    std::pair<Image, Property> getMyImage(int index);
};

I run command swig -c++ -python Test.swig.

I compile Test_wrapper.cxx in Visual Studio, It occurs error following this:

error C2512: 'Image' : no appropriate default constructor available

So I tried with swig -c++ -python -nodefaultctor Test.swig. But it was same.

============UPDATE============

The problem is std::pair<Image, Property>. When pair create, it calls the constructor of arguments. Image has no default constructor. So erorr occurs.

How can I fix it? Thanks.

like image 273
KDEV Avatar asked Mar 27 '26 23:03

KDEV


1 Answers

I finally figured out a way to make this work. Firstly, since you've got pass-by-value semantics for addMyImage and getMyImage you need to use %feature("valuewrapper") to turn on pass-by-value wrapping transformation in the generated code otherwise you'll get default constructed pairs in the generated code.

Secondly you need to prevent SWIG from exposing the std::pair constructor that takes no arguments. (This I think is different to the %nodefaultctor directive because one such constructor is explicitly written and not simply assumed to exist). It took me a long time to realise the correct syntax for the easiest(?) way do do this which I believe is using advanced renaming.

So you need to add two lines before your %include <std_pair.i> directive:

%feature("valuewrapper") std::pair<Image,Property>;
%rename("$ignore",$isconstructor,fullname=1) "std::pair<(Image,Property)>";
%include "std_pair.i"

This does however disable all the constructors in std::pair<Image,Property>.

like image 74
Flexo Avatar answered Mar 31 '26 05:03

Flexo



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!