对函数使用SWIG作为输入参数
Using SWIG for functions with functions as input parameter
考虑以下最小示例:我有一个c++函数'myfun',它接受一个数字和另一个函数作为输入,并返回在x处求值的函数:
double myfun(double x, double (*f)(double y))
{返回f (x);}
我将这段代码存储在'test.cpp'中。对应的头文件'test.hpp'中的代码只是
double myfun(double x, double (*f)(double y));
现在,我尝试使用SWIG从Python访问'myfun'。"痛饮。我的文件如下所示:
%module test
% {
#include "test.hpp"
%}
Double myfun(Double x, Double (*f)(Double y));
每当我尝试在Python中调用这个函数时,例如使用
from test import myfun
Myfun (2, lambda y: y**2)
我收到错误:
方法'myfun',参数2类型'double (*)(double)'
所以我的问题很简单:如何修改"swig"。i'的文件,这样我可以传递任何(合适的Python)函数'myfun'?(这个问题在某种程度上与这篇文章有关,如何包装一个c++函数,它在python中使用SWIG',但不同的是,这里我没有指定c++中的输入函数,而是我想把它作为一个自由的'参数')。
回调在编写绑定时需要额外的处理,这在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++代码)。
如果你可以同时控制这两个方面,那么一个解决方法是创建一个包含回调的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的函数也可以有上下文)。
完整的示例可以从这里下载
根据文档(重点是我的):
尽管SWIG通常不允许用目标语言编写回调函数,但这可以通过使用类型映射和其他高级SWIG特性来完成。
如果你想更深入地了解这个主题,建议你读这一章。
无论如何,看起来它并不是该工具的一个预期的关键特性。您能做的最好的事情可能是获得一个围绕Python设计的解决方案,并且不能与其他目标语言一起工作,但这通常不是Swig用户想要的。
请注意,您仍然可以在C/c++中编写回调并将其导出为常量,然后在目标语言中使用它们。
- 将输入参数作为右值引用传递?
- 是否可以在命令行中将输入参数传递给可执行文件
- C++基于输入参数的动态代码生成
- 我想知道为什么"std::unique_ptr<int> foo(新 int)"是合法的,因为"std::<int>unique_ptr"要求输入参数类型应该是"int"?
- 如何使用输入参数作为文件的传递?
- 在函数中使用运算符重载,在 c++ 中使用 const 类型输入参数
- 提供变量作为 MATLAB 系统命令的输入参数,以便C++可执行文件
- 函数的函数无法识别输入参数
- 当迭代器(输入参数)通常不是constexpr时,constexpr算法真的有用吗
- 如何将一个使用参数包和typename的类作为函数(c++)的输入参数
- CvMat:输入参数的大小不匹配
- 在什么情况下,使用'const T*'输入参数比'const T&'更可取?
- std::具有两个输入参数的矢量构造函数
- GoogleMock:如何根据另一个输入参数设置ArgReferee?
- 模板化函数以从输入参数推断返回类型 stl-container
- GoogleMock:如何验证输入参数的调用次数?
- 当我将 char 数组发送到输入参数为字符串的函数时会发生什么?
- 应该接受不同输入参数的纯虚函数 - 应该如何实现
- C++主函数的输入参数
- STD :: Atomic_fetch为什么将指针作为其输入参数