Volodymyr Hnatiuk
Volodymyr Hnatiuk

Reputation: 197

Input sting for wrapped C++ function doesn't changing SWIG

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

Answers (2)

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

Anya Shenanigans
Anya Shenanigans

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

Related Questions