通过SWIG传递函数指针数组
Pass array of function pointers via SWIG
在https://stackoverflow.com/a/22965961/353337的帮助下,我能够创建一个简单的示例,说明如何通过Python将一个函数指针传递给函数。具体地说,与
double f(double x) {
return x*x;
}
double myfun(double (*f)(double x)) {
fprintf(stdout, "%gn", f(2.0));
return -1.0;
}
%module test
%{
#include "test.hpp"
%}
%pythoncallback;
double f(double);
%nopythoncallback;
%ignore f;
%include "test.hpp"
我可以调用
import test
test.f(13)
test.myfun(test.f)
并得到预期的结果。
现在,我想改变myfun
的签名,以允许数组函数指针(都具有相同的签名),例如,
double myfun(std::vector<double (*)(double)>)
我如何适应.i
文件?
test.myfun([test.f, test.g])
我制作了下面的测试用例来说明您要做的事情。它有一个真正的myfun(const std::vector<double(*)(double)>&)
实现,使生活更有趣:
#include <vector>
double g(double x) {
return -x;
}
double f(double x) {
return x*x;
}
typedef double(*pfn_t)(double);
std::vector<double> myfun(const std::vector<pfn_t>& funs, const double d) {
std::vector<double> ret;
ret.reserve(funs.size());
for(auto && fn : funs)
ret.emplace_back(fn(d));
return ret;
}
我原以为我们所需要做的就是使用:
%include <std_vector.i>
%template(FunVec) std::vector<double(*)(double)>;
%template(DoubleVec) std::vector<double>;
%include "test.h"
但是SWIG 3.0(来自Debian稳定版)不能正确处理这个FunVec
,并且产生的模块无法编译。所以我添加了一个typemap作为解决方案:
%module test
%{
#include "test.h"
%}
%pythoncallback;
double f(double);
double g(double);
%nopythoncallback;
%ignore f;
%ignore g;
%typemap(in) const std::vector<pfn_t>& (std::vector<pfn_t> tmp) {
// Adapted from: https://docs.python.org/2/c-api/iter.html
PyObject *iterator = PyObject_GetIter($input);
PyObject *item;
if (iterator == NULL) {
assert(iterator);
SWIG_fail; // Do this properly
}
while ((item = PyIter_Next(iterator))) {
pfn_t f;
const int res = SWIG_ConvertFunctionPtr(item, (void**)(&f), $descriptor(double(*)(double)));
if (!SWIG_IsOK(res)) {
assert(false);
SWIG_exception_fail(SWIG_ArgError(res), "in method '" "foobar" "', argument " "1"" of type '" "pfn_t""'");
}
Py_DECREF(item);
tmp.push_back(f);
}
Py_DECREF(iterator);
$1 = &tmp;
}
%include <std_vector.i>
// Doesn't work:
//%template(FunVec) std::vector<double(*)(double)>;
%template(DoubleVec) std::vector<double>;
%include "test.h"
基本上,所有这些都是为函数指针类型的向量添加一个'in'类型映射。该typemap只是对Python给出的输入进行迭代,并从Python可迭代对象构建一个临时的std::vector
。
这足以使以下Python按预期工作:
import test
print test.g
print test.f
print test.g(666)
print test.f(666)
print test.myfun([test.g,test.f],123)
相关文章:
- 添加到数组指针
- C++语法差异:二维和一维数组(指针算术)
- 数组指针表示法C++(移动数组时)
- 复制后删除原始数组指针将前 3 个字节设置为 0
- C++访问指向结构的指针中的类数组指针
- C++编译时使用 constexpr 字符数组指针分配静态数组?
- std::flush可以用于将对象指针转换为其封闭数组指针吗
- 创建<int>对整数数组指针的矢量引用 (C++)
- 将 2D 数组指针传递给 C++ 中的函数
- 创建指针是否超过非数组指针的末尾,而不是从 C++17 中的一元运算符和未定义的行为派生?
- 队列数组指针 (C++)
- C++数组指针上的删除操作
- 对于循环不循环和检测字符数组 [指针和字符数组]
- 如何初始化数组指针对象
- 如何正确传递 2D 数组指针作为参数
- 从数组指针中获取怪异的数字
- 初始化std :: unique_ptr作为原始数组指针的初始化
- 将结构数组指针从C#传递到C
- STD :: Sort将数组指针设置为NULL
- C++数组指针错误无法将“int*”转换为“int**”