包装C ++函数的输入sting不会改变SWIG

时间:2016-12-06 14:42:11

标签: python c++ swig

我为C ++库制作Python包装器。

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);

使用以下命令生成_mylib.so后:

g++ -fPIC -Wall -Wextra -shared mylib_wrap.cxx -o _mylib.so -L. -lmylib -I/usr/include/python2.7/ -lpython2.7

我接下来会这样做:

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)

执行我的函数后,x返回正确的方法响应。我也有我的功能控制台输出。但结果字符串不会改变。 如果我使用“some text”初始化结果字符串,并再次调用我的函数,print result将返回"some text"。我做错了什么?

2 个答案:

答案 0 :(得分:1)

在这种情况下SWIG做了多少诡计并不重要,它无法解决python字符串不可变的事实 - 一旦设置,你就无法改变它们。

SWIG生成的代码看起来像这样:

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;

请注意,它从传入的字符串中创建一个新字符串,然后在最后对其进行核实 - 毕竟,字符串是不可变的。

懒惰的解决方案只是返回json字符串,例如接口:

std::string getResult(std::string &path)

会产生预期的效果。

现在,如果您想要一个特殊的返回值,它的对象以及其中包含的所有内容。

答案 1 :(得分:1)

在界面中使用它的最简单方法是使用%inline创建一个返回结果的重载:

%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;
    }
%}

您甚至不需要向SWIG显示getResult的真实版本。

还有其他选项(例如,使用带有numinputs = 0的输入类型映射和用于修改返回值的argout类型映射),但它们更复杂,并且通常对其他语言的可移植性更低。