我为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"
。我做错了什么?
答案 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类型映射),但它们更复杂,并且通常对其他语言的可移植性更低。