Reputation: 197
I make Python wrapper for C++ library.
mylib.i:
%module mylib
%include <std_string.i>
%{
#include "mylib.h"
%}
%apply const std::string & {std::string &};
%apply std::string & {std::string &};
int getResult(const std::string& path, std::string& result);
mylib.h:
#pragma once
#include <string>
myEnum {foo=0, bar};
myEnum getResult(const std::string& path, std::string& result);
After generating _mylib.so with following command:
g++ -fPIC -Wall -Wextra -shared mylib_wrap.cxx -o _mylib.so -L. -lmylib -I/usr/include/python2.7/ -lpython2.7
I do next:
LD_LIBRARY_PATH=. python Python 2.7.2 (default, Dec 6 2016, 10:43:39)
[GCC 4.8.4] on linux4
Type "help", "copyright", "credits" or "license" for more information.
>>> import _mylib
>>> result= ""
>>> x = _mylib.getResult("somePath",result)
After execution of my function, x
returns right respond of method. Also I have console output from my function. But result string doesn't changing.
If I init result string with "some text", and call my function again, print result
return "some text"
. What I'm doing wrong?
Upvotes: 1
Views: 117
Reputation: 88801
The simplest way to get this to work inside your interface is to use %inline
to create an overload that returns the result instead:
%module mylib
%include <std_string.i>
%{
#include "mylib.h"
%}
%inline %{
int getResult(const std::string& path) {
std::string temp;
const int ret = getResult(path, temp);
if (ret != good) abort(); // TODO exceptions
return temp;
}
%}
You don't even need to show SWIG the real version of getResult
.
There are other options (e.g. use an input typemap with numinputs=0 and an argout typemap to modify the return value), but they're more complicated and generally less portable to other languages.
Upvotes: 1
Reputation: 94859
Doesn't matter how much trickery SWIG does in this case, it can't get around the fact that python strings are immutable - once set, you can't change them.
The SWIG generated code looks vaguely like this:
std::string *arg1 = make a new std::string from path;
std::string *arg2 = make a new std::string from result;
result = (int)getResult((std::string const &)*arg1,*arg2);
resultobj = SWIG_From_int(static_cast< int >(result));
if (SWIG_IsNewObj(res1)) delete arg1;
if (SWIG_IsNewObj(res2)) delete arg2;
Note that it makes a new string from the strings passed in, and then nukes them at the end - after all, strings are immutable.
a lazy solution would be simply returning the json string e.g. an interface of:
std::string getResult(std::string &path)
would have the desired effect.
Now if you want a special return value, it's objects and all that would be entailed in that.
Upvotes: 1