Dears, I use SWIG to generate Python bindings to a C++ API (and it works great!) but I have serious difficulty wrapping a function that takes a vector of enum as argument. I have built a minimal example to simplify the debugging, which I put as an attachment to this issue. It seems to me that the example should work, at least it works well for a vector of integer argument.
The need is pretty simple : we have a C++ method with the following signature:
void Run(const std::vector<double> & in, std::vector<int> & out, std::vector<testing::Status> & status)
where testing::Status is an enum
and we will like to obtain a Python method like:
out, status = Run(in)
Using the attached example, the swig executable does not raise any error, and the Python Run method can be ran, but the output value status cannot be used, an error is raised:
status: (<Swig Object of type 'testing::Status *' at 0x7fa441156450>, <Swig Object of type 'testing::Status *' at 0x7fa441156660>) swig/python detected a memory leak of type 'testing::Status *', no destructor found. swig/python detected a memory leak of type 'testing::Status *', no destructor found.
Here are the different files that can be used to reproduce the error:
mylib.h, the C++ to wrap in Python
#include <vector>
namespace testing
{
typedef enum
{
Ok = 0,
Error = 1,
} Status;
class Algo
{
public:
void Run(const std::vector<double> & in, std::vector<int> & out, std::vector<testing::Status> & status)
{
status.resize(in.size());
out.resize(in.size());
for (int i=0; i<in.size(); ++i) {
out[i] = i;
status[i] = Status::Ok;
}
}
};
}
mymodule.i, the SWIG interface file
%module mymodule
%{
#include "mylib.h"
%}
%include "std_vector.i"
%include "typemaps.i"
%define STD_TEMPLATE(TYPE...)
%template() TYPE;
%apply TYPE& OUTPUT {TYPE&}
%typemap(argout) const TYPE& {
// do nothing for const references
}
%typemap(out) (TYPE&) = (const TYPE&);
%enddef
STD_TEMPLATE (std::vector <int>);
STD_TEMPLATE (std::vector <double>);
STD_TEMPLATE (std::vector < testing::Status >);
%include "mylib.h"
build.sh, the build command line used to compile binaries
${swig_install}/bin/swig \
-I. \
-I${swig_install}/share/swig/${swig_version}/python \
-I${swig_install}/share/swig/${swig_version} \
-c++ -python \
-outdir . \
-o "mymodule.cxx" \
"mymodule.i"
g++ -L${python_install}/lib -lpython3 \
-I${python_install}/include/python \
-I. \
-std=c++11 -shared -fPIC \
mymodule.cxx -o _mymodule.so
run.py, the example in Python that raises the error
import mymodule as mm
algo = mm.Algo()
out, status = algo.Run([1.1, 2.2])
print("out:", out)
print("status:", status)
SWIG doesn't know what to do with the vector of enum outputs. One way is to handle the typemaps yourself:
mylib.i
Output (same mylib.h and run.py):