SWIG c++ Python:通过引用或指针包装int

时间:2021-04-26 21:23:25

I'm trying to wrap some C++ functions into a Python wrapper. For this, it seems SWIG is a nice and easy way.

我试图将一些c++函数封装到Python包装器中。对于这一点,SWIG似乎是一个很好的和容易的方法。

Wrapping works, but I get a problem when passing integers by reference or by pointer. Since Python cannot work with references, SWIG internally converts these to pointers.

包装工作,但当通过引用或指针传递整数时,会遇到问题。由于Python不能处理引用,SWIG在内部将这些转换为指针。

Some simple example code:

一些简单的示例代码:

Blaat.hpp :

Blaat。高压泵:

#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

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:

Blaat.i:

%module Blaat
%{
/* Includes the header in the wrapper code */
#include "Blaat.hpp"
%}

/* Parse the header file to generate wrappers */
%include "Blaat.hpp"

Than convert the code into a Python wrapper:

将代码转换为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

This all works fine. Now, I start Python and do:

这一切都没问题。现在,我开始讲Python并做:

from Blaat import *
a = Blaat()
b = int(1)
a.setA(b) <-- fine, calls setA() function fine
a.getA(b) <-- does not work

At the "getA()" call, the following error occurs:

在“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 &'

Note that I get this problem both when passing the argument by reference and by pointer. Looking at the generated "Blaat_wrap.cxx" file, it stops at the actual type conversion:

注意,在通过引用和指针传递参数时,我都会遇到这个问题。查看生成的“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 &""'"); 
}

This means that the function SWIG_ConvertPtr() fails, which is strange because it seems that the type it checks for is SWIGTYPE_p_int. From the "setA()" function, we see that the type conversion works (if passing by value).

这意味着函数SWIG_ConvertPtr()失败,这很奇怪,因为它检查的类型似乎是SWIGTYPE_p_int。从“setA()”函数中,我们可以看到类型转换工作(如果按值传递)。

The SWIG documentation tells me):

SWIG文档告诉我):

C++ references are supported, but SWIG transforms them back into pointers. For example, a declaration like this :

支持c++引用,但是SWIG将它们转换回指针。例如,这样的声明:

class Foo { public: double bar(double &a); }

类Foo {public: double bar(double &a);}

has a low-level accessor

有一个低级访问器

double Foo_bar(Foo *obj, double *a) { obj->bar(*a); }

双Foo_bar(Foo *obj, double *a) {obj->bar(*a);}

Can someone throw in the thing I'm missing? I'm quite stuck at this point... Found this post, but this did not help either

有人能把我丢失的东西扔进去吗?我现在很为难……找到了这个帖子,但这也无济于事

2 个解决方案

#1


6  

I don't think python has the concept of return by reference, but here is my solution:

我不认为python有引用返回的概念,但我的解决方案是:

Blaat.i:

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:

b.py:

from Blaat import *
a = Blaat()
b = int(1)
a.setA(b)
b = a.getA()

Running:

运行:

python b.py
[Blaat::setA] fA = 1
[Blaat::getA] fA = 63

#2


2  

Thanks Chris, this works! After a bit of more digging, it seems that the SWIG documentation is not complete.

谢谢克里斯,这个工作!在进一步挖掘之后,SWIG文档似乎还没有完成。

SWIG type conversion using the typemaps.i library is described here. What I get from the example is that you HAVE to manually specify that you want an argument to be used as output (which means that the SWIG documentation on 'pointers and references' only holds for INPUT arguments only!).

使用类型转换刷新类型。这里描述了i库。我从示例中得到的是,您必须手动指定要将一个参数用作输出(这意味着关于“指针和引用”的SWIG文档仅用于输入参数!)

For the simple example above, it is sufficient to just including the .hpp file and let SWIG handle everything automatically.

对于上面的简单示例,只要包含.hpp文件并让SWIG自动处理一切就足够了。

Blaat.i:

Blaat.i:

%module Blaat
%include typemaps.i
%apply int &OUTPUT { int & fA };
%{
#include "Blaat.hpp"
%}

%include "Blaat.i"

PS: The Blaat.cpp file couts the wrong value, it should of course cout mA instead of fA since fA is set after the cout...

PS:Blaat。cpp文件输出了错误的值,当然应该是cout mA而不是fA,因为fA是在cout之后设置的。

#1


6  

I don't think python has the concept of return by reference, but here is my solution:

我不认为python有引用返回的概念,但我的解决方案是:

Blaat.i:

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:

b.py:

from Blaat import *
a = Blaat()
b = int(1)
a.setA(b)
b = a.getA()

Running:

运行:

python b.py
[Blaat::setA] fA = 1
[Blaat::getA] fA = 63

#2


2  

Thanks Chris, this works! After a bit of more digging, it seems that the SWIG documentation is not complete.

谢谢克里斯,这个工作!在进一步挖掘之后,SWIG文档似乎还没有完成。

SWIG type conversion using the typemaps.i library is described here. What I get from the example is that you HAVE to manually specify that you want an argument to be used as output (which means that the SWIG documentation on 'pointers and references' only holds for INPUT arguments only!).

使用类型转换刷新类型。这里描述了i库。我从示例中得到的是,您必须手动指定要将一个参数用作输出(这意味着关于“指针和引用”的SWIG文档仅用于输入参数!)

For the simple example above, it is sufficient to just including the .hpp file and let SWIG handle everything automatically.

对于上面的简单示例,只要包含.hpp文件并让SWIG自动处理一切就足够了。

Blaat.i:

Blaat.i:

%module Blaat
%include typemaps.i
%apply int &OUTPUT { int & fA };
%{
#include "Blaat.hpp"
%}

%include "Blaat.i"

PS: The Blaat.cpp file couts the wrong value, it should of course cout mA instead of fA since fA is set after the cout...

PS:Blaat。cpp文件输出了错误的值,当然应该是cout mA而不是fA,因为fA是在cout之后设置的。