Search code examples
pythonc++swig

How to initialize a variable from a class method binding C++ with Swig


I want to bind some C++ code to python thanks to swig. In my C++ code, I initialize some important variables via class methods. However, this kind of initialization seems to create some troubles to swig which returns Error: Syntax error - possibly a missing semicolon.

Below is a very simple example extracted from swig documentation, where I only add this kind of initialization from a method. This example is made of 3 files (my_class.hpp ; my_class.cpp ; py_myclass.i).

my_class.hpp:

#ifndef MYCLASS_H
#define MYCLASS_H

class MyClass {
    public:
    float getSqr();
    float getSqr(float _v);
    
    private:
    float value=2.;
};

float toto=MyClass().getSqr(3.);     // the only line I added !

#endif

my_class.cpp

#include "my_class.hpp"

float MyClass::getSqr() {
    return getSqr(value);
}

float MyClass::getSqr(float value) {
    return value*value;
}

py_myclass.i

%module py_myclass

%{
#include "my_class.hpp"
%}

%include "my_class.hpp"

So, the only modification I made from swig documentation was to add the initialization line float toto=MyClass().getSqr(3.);. I tried to play around a bit with it, but I always get the syntax error.

From these files, I execute swig to create wrappers. I do it with the command line:

swig -python -c++ -o py_myclass_wrap.cpp py_myclass.i

which yields me the following error:

py_myclass.i:13: Error: Syntax error - possibly a missing semicolon.

So, is there a way to accomplish this kind of initialization with swig ?

I also tried to add the line %ignore toto; before the last %include "my_class.hpp" in the file py_myclass.i, but it seems that the ignoring was ignored itself.


Solution

  • SWIG's C++ parser doesn't support that initialization syntax, it seems.

    Instead, in the header use:

    extern float toto;
    

    In the .cpp file initialize it:

    float toto=MyClass().getSqr(3.);
    

    Then SWIG will only see the extern declaration since it only parses the .hpp file. Here's a run of the result:

    >>> import py_myclass
    >>> py_myclass.cvar.toto
    9.0
    >>> c=py_myclass.MyClass()
    >>> c.getSqr()
    4.0
    >>> c.getSqr(9)
    81.0