为包装的C+输入sting+;函数不';不换水 我为C++库制作Python包装器。

为包装的C+输入sting+;函数不';不换水 我为C++库制作Python包装器。,python,c++,swig,Python,C++,Swig,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.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);
我下一步要做:

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)
执行my函数后,
x
返回方法的右响应。我的函数还有控制台输出。但结果字符串并没有改变。
如果我用“some text”初始化结果字符串,然后再次调用我的函数,
print result
返回
“some text”
。我做错了什么

不管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;
会有预期的效果


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

在接口内部实现此功能的最简单方法是使用
%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;
    }
%}
%mylib模块
%包括
%{
#包括“mylib.h”
%}
%内联%{
int getResult(const std::string和path){
std::字符串温度;
const int ret=getResult(路径,温度);
if(ret!=good)abort();//TODO异常
返回温度;
}
%}
您甚至不需要向SWIG显示真正版本的
getResult


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

查看该代码,您正在传递变量
json
,不是变量
result
,因此我不希望它更改变量
result
的值。@Petesh抱歉,忘记了在复制粘贴后更改变量名。@Petesh但是输入参数名正确,问题没有消失。这不是一个好方法。但是我可以在接口文件中以某种方式包装我的函数吗。在接口中定义一些调用getResult函数的函数?您应该能够进行某种形式的包装来完成所需的操作。这确实是因为python的工作方式,您无法让这个接口按原样工作。@VolodymyrHnatiuk当然可以,或者您可以将它拆分为
%{%}
,但您最终会将它的一些部分(即声明)编写两次,那么如何呢?也许你有一些例子@Flexo@VolodymyrHnatiuk这与修改问题中的代码没有什么不同-编辑mylib.h以添加另一个声明,即SWIG模块文件中的声明,并将我在代码中显示的相同实现添加到一个翻译单元中,然后链接到共享对象。不,你不明白我的意思。我无法更改mylib.h,因此无法向mylib.h添加另一个函数声明。我问过您是否能够使用另一个函数声明添加mulib_module.h,并使用函数实现创建mylib_module.cpp,该函数实现现在位于%inline%{%}中。并使用所有这些调用getResult(path,temp);来自mylib.so。@FlexoI看不出%inline有什么问题-它非常简洁地完成了您想要的操作-SWIG在包装它的同时自动将其放入.cpp文件中。
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;
std::string getResult(std::string &path)
%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;
    }
%}