2016-08-19 76 views
4

https://stackoverflow.com/a/22965961/353337的帮助下,我能够创建一个简单的例子,说明如何通过Python将一个函数指针传递给函数。具体来说,通过SWIG传递函数指针的数组

%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文件?

理想的情况下,Python的通话将通过列表

test.myfun([test.f, test.g]) 
+0

@πάνταῥεῖ的基本工作的例子是一样的,但问题是不同的。请取消标记为dup。 –

+0

请改善你的问题第一。 –

+0

什么不清楚? –

回答

1

我做下面的测试案例来说明你想要做什么。它有一个真正落实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" 

然而痛饮3.0(来自Debian稳定版)不能正确处理FunVec,并且生成的模块不能编译。所以我增加了一个类型映射作为一种解决方法:

%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" 

基本上所有这样做是“在”类型表添加一个函数指针类型的载体。该类型图只是对从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)