使用SWIG作为具有输入参数功能的函数

时间:2016-11-11 06:13:30

标签: python c++ swig

考虑以下最小的例子:我有一个C ++函数' myfun'它接受一个数字和另一个函数作为输入,并返回在x:

评估的函数
  

双myfun(双x,双(* f)(双y))
  {    return f(x);   }

我将此代码存储在' test.cpp'中。相应头文件中的代码' test.hpp'简直就是

  

double myfun(double x,double(* f)(double y));

现在,我尝试访问“myfun'来自Python使用SWIG。 ' swig.i'文件如下:

  

%模块测试
  %{
   #include" test.hpp"
  %}
  double myfun(double x,double(* f)(double y));

每当我尝试在Python中调用此函数时,例如与

  

从测试导入myfun
  myfun(2,lambda y:y ** 2)

我收到错误:

  

方法' myfun',参数2类型' double(*)(double)'

所以我的问题很简单:如何修改' swig.i'文件,以便我可以将任何(合适的Python)功能传递给' myfun&#39 ;? (这个问题与这篇文章有点相关How to wrap a c++ function which takes in a function pointer in python using SWIG'但不同之处在于我在C ++中没有指定输入函数,而是我希望将它保留为免费参数&# 39)。

2 个答案:

答案 0 :(得分:1)

回写在编写绑定时需要额外的处理,这在SWIG中尚未得到支持,显然没有真正的解决方法。

重点是SWIG是关于从Python(和其他语言)调用C,而不是从C调用Python。

我们正在使用SIP而不是更复杂的绑定生成器(但是C ++ / Python特定的)。 SIP支持回调,甚至从C ++类继承Python类。

该工具非常强大,是PyQt绑定的引擎。

但请注意,Python中的可调用函数不仅仅是C ++中的函数,因为它可以包含上下文(它可以是闭包)。在C ++代码中:

int callF(int (*f)(int, int), int a, int b) {
    return f(a, b);
}

只能调用一个纯粹的无上下文函数,因此传递一般的Python回调是不可能的,因为没有足够的信息(唯一的解决方案是分配预编译的trampolines或在运行时生成C ++代码)。 / p>

如果你可以控制双方,但是解决方法是创建一个包含回调的C类并在Python中派生它。例如:

struct CBack {
    virtual int operator()(int x, int y) const {
        return x+y;
    }
    virtual ~CBack() {}
};

int callF(const CBack& f,
          int xv, int yv)
{
    return f(xv, yv);
}

然后从CBack派生一个Python类并传递:

class Add(CBack):
    def __call__(self, x, y):
        return x + y

class Mul(CBack):
    def __call__(self, x, y):
        return x * y

print callF(Add(), 3, 7) # will print 10
print callF(Mul(), 3, 7) # will print 21

在这种情况下,你也可以传递一个(包裹的)lambda

def cback(f):
    class PyCBack(CBack):
        def __call__(self, x, y):
            return f(x, y)
    return PyCBack()

print callF(cback(lambda x, y: x*y), 3, 7)

换句话说,一个阻抗问题是C ++的函数与Python的函数不同(Python的函数也可以有上下文)。

可以从here下载完整示例。

答案 1 :(得分:0)

根据documentation(强调我的):

  

虽然 SWIG通常不允许使用目标语言编写回调函数,但这可以通过使用文字图和其他高级SWIG功能来实现。

如果您想深入了解该主题,

This是建议的章节 无论如何,它看起来不是该工具的预期关键功能 您可以做的最好的事情是获得一个围绕Python设计的解决方案,并且不能与其他目标语言一起使用,但通常不是Swig的用户想要的。

请注意,您仍然可以使用C / C ++编写回调函数并将它们作为常量导出,然后使用目标语言中的它们。 有关详细信息,请参阅上述文档。