I have a C++ function in which two arguments are given as the following example.
void func(int& n, char** data)
{
*data = other_func1(); // returns a char array
n = other_func2(); // returns the length of the array
}
I can easily use this function in C or C++, but I do not know how I can call it from a Python module generated with SWIG. I suppose that I will have to write another C++ function which returns, for example, std::pair. But if possible, I would like to know a workaround in the Python side. Could anyone help?
For quite a lot of cases (e.g. int *n
) it would be sufficient to write:
%apply int *OUTPUT { int *n };
which uses some default typemaps that SWIG provides for output parameters. (There is also INOUT and INPUT which are similar).
In this instance though we don't quite match any of the predefined cases, so we need to do the same thing manually. That's basically two typemaps per argument - an input typemap which creates something temporary for the actual function call and uses that instead of some real input and an argout that marshals the result back from the temporary to Python. In the case of Python it makes sense to use a tuple for returning multiple arguments.
An example:
%module test
%typemap(in,numinputs=0) int& n (int temp) "$1 = &temp;"
%typemap(in,numinputs=0) char **data (char *temp) "$1 = &temp;"
%typemap(argout) char **data {
%append_output(PyString_FromString(*$1));
}
%typemap(argout) int& n {
%append_output(PyInt_FromLong(*$1));
}
%inline %{
void foo(int& n, char **data) {
static char str[] = "Hello world";
*data = str;
n = sizeof str;
}
%}
Points to note:
The temporary variables (int temp
, char *temp
) automatically get renamed which stops the apparent name clash. %append_output
is a SWIG macro that expands to add something to the back of the $result
tuple in Python. If your function foo
were dynamically allocated memory you'd need to handle that. The freearg typemap is often useful if the in typemap needs to dynamically allocate memory.
This was sufficient to allow me to compile and run it like:
import test
len,str = test.foo()
print len
print str
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