使用SWIG控制器将python中的numpy函数传递给C++

Passing a numpy function in python to C++ using SWIG directors

本文关键字:函数 C++ numpy 中的 SWIG 控制器 python 使用      更新时间:2023-10-16

我的代码主要在C++中,但我想使用SWIG director选项在python中重新定义C++虚拟函数,然后将该函数传递回C++。以下是一个简化的示例。

这是我在C++中的基类,带有一个虚拟函数funfun接收(double* x, int n),它允许我将numpy数组传递给它

class base{
public:
    virtual double fun(double* x, int n){return 0.0;}
};

我有另一个接受这个基类的类:

class main{
public:
    base* b_;
    main(base& b){
        b_ = &b; 
    }
};

这个类有一个构造函数,它接收一个基类并存储指向它的指针(b_)。

我可以成功地将swig接口编译成一个名为mymodule的模块,确保启用控制器(请参阅下面的swig接口文件),并且,根据swig控制器文档,我继承了基类并重新定义了虚拟函数fun,如下所示:

import mymodule
class base(mymodule.base):
    def __init__(self):
        super(base,self).__init__()
    def fun(self,x):
        return x[0]

然后我将其传递到main类:

b = base()
m = mymodule.main(b)

然而,当我尝试m.b_.fun(array([1.,2.]))时,我会得到TypeError:

TypeError: 'SwigPyObject' object has no attribute '__getitem__'

关于如何让它发挥作用,有什么想法吗?我想,当我将b传递到mymodule.main时,C++将x视为一个双*指针,不知道该怎么处理它。

顺便说一下,这是我的swig接口文件:

%module(directors="1") mymodule
%{
#define SWIG_FILE_WITH_INIT
/* Includes the header in the wrapper code */
#include "myclasses.h"
%}
%feature("director") base;
%init %{
import_array();
%}
%apply (double* IN_ARRAY1, int DIM1) {(double* x, int n)};
/* Parse the header file to generate wrappers */
%include "myclasses.h"

这看起来像是Python的所有权问题。

向SWIG:提供提示

%new double *fun(double* IN_ARRAY1, int DIM1) {(double* x, int n)};

请注意指向函数本身的指针。当使用%new时,Python模块将为对象分配正确的所有权。这就是为什么在调用中可以使用值而不能使用变量的原因。

似乎director没有识别您的fun(double* x, int n)的Python实现;它并没有对该函数进行重载。

我怀疑原因是您的Python实现使用numpy作为参数。请注意,director将调用抽象函数或已实现函数。

另一方面,%apply (double* IN_ARRAY1, int DIM1) {(double* x, int n)}只声明了用于在Python中封装函数的typemap逻辑,而不是向director声明。请注意,这就是b.fun(array([1.,2.])工作的原因!也就是说,你应该向导演声明类型映射逻辑。

在这里你可以找到如何做到这一点:

%typemap(directorin,numinputs=1) (double *x, int n)
{
    npy_intp dim = $2;
    $input = PyArray_SimpleNewFromData(1, &dim, NPY_DOUBLE, (void *)$1);
}

希望这能解决你和其他未来的问题:)。我遇到了类似的问题,花了几天时间试图弄清楚。