我正在尝试将一些C ++函数包装到Python包装器中。 为此,似乎SWIG是一种不错的方式。
包装有效,但是通过引用或指针传递整数时出现问题。 由于Python无法使用引用,因此SWIG在内部将这些转换为指针。
一些简单的示例代码:
Blaat.hpp:
#ifndef __BLAAT_HPP__
#define __BLAAT_HPP
class Blaat
{
public:
int mA;
float mB;
public:
Blaat() {}
void getA(int & fA);
void setA(const int fA);
~Blaat() {}
};
#endif // __BLAAT_HPP__
Blaat.cpp
#include "Blaat.hpp"
#include <iostream>
void Blaat::getA(int & fA) {
std::cout << "[Blaat::getA] fA = " << fA << std::endl;
fA = mA;
}
void Blaat::setA(const int fA) {
std::cout << "[Blaat::setA] fA = " << fA << std::endl;
mA = fA;
}
Blaat.i:
%module Blaat
%{
/* Includes the header in the wrapper code */
#include "Blaat.hpp"
%}
/* Parse the header file to generate wrappers */
%include "Blaat.hpp"
将代码转换为Python包装器:
#!/bin/sh
swig -python -c++ -v $1.i
gcc -c $1_wrap.cxx -fPIC -I/usr/include/python2.6
gcc -shared $1_wrap.o -o _$1<library_path> so -L. -l$1
一切正常。现在,我启动Python并执行:
from Blaat import *
a = Blaat()
b = int(1)
a.setA(b) <-- fine, calls setA() function fine
a.getA(b) <-- does not work
在“getA()”调用中,发生以下错误:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "Blaat.py", line 86, in getA
def getA(self, *args): return _Blaat.Blaat_getA(self, *args)
TypeError: in method 'Blaat_getA', argument 2 of type 'int &'
请注意,通过引用和指针传递参数时,我都会遇到此问题。 查看生成的“Blaat_wrap.cxx”文件,它会在实际的类型转换处停止:
res2 = SWIG_ConvertPtr(obj1, &argp2, SWIGTYPE_p_int, 0 );
if (!SWIG_IsOK(res2)) {
SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Blaat_getA" "', argument " "2"" of type '" "int &""'");
}
这意味着函数SWIG_ConvertPtr()失败,这很奇怪,因为它检查的类型似乎是SWIGTYPE_p_int。 从“setA()”函数中,我们看到类型转换有效(如果通过值传递)。
The SWIG documentation tells me):
支持C ++引用,但SWIG将它们转换回来 指针。例如,这样的声明:
class Foo {public:double bar(double&amp; a); }
有一个低级访问者
double Foo_bar(Foo * obj,double * a){obj-&gt; bar(* a); }
有人可以投入我失踪的东西吗?我现在很困惑...... Found this post, but this did not help either
答案 0 :(得分:7)
我认为python没有引用返回的概念,但这是我的解决方案:
Blaat.i:
%module Blaat
%include typemaps.i
%apply int &OUTPUT { int & fA };
%{
/* Includes the header in the wrapper code */
#include "Blaat.hpp"
%}
/* Parse the header file to generate wrappers */
class Blaat
{
public:
Blaat();
void getA(int & fA);
void setA(const int fA);
~Blaat();
};
b.py:
from Blaat import *
a = Blaat()
b = int(1)
a.setA(b)
b = a.getA()
运行:
python b.py
[Blaat::setA] fA = 1
[Blaat::getA] fA = 63
答案 1 :(得分:2)
谢谢Chris,这很有效! 经过一番挖掘后,似乎SWIG文档还没有完成。
SWIG type conversion using the typemaps.i library is described here。 我从示例中得到的是,您必须手动指定您希望将参数用作输出(这意味着关于“指针和引用”的SWIG文档仅适用于INPUT参数!)。
对于上面的简单示例,仅包含.hpp文件就足够了,让SWIG自动处理所有内容。
Blaat.i:
%module Blaat
%include typemaps.i
%apply int &OUTPUT { int & fA };
%{
#include "Blaat.hpp"
%}
%include "Blaat.i"
PS:Blaat.cpp文件判断错误的值,当然应该用cout mA而不是fA,因为在cout之后设置了fA ...