是否可以调用一个python函数,该函数具有来自boost::python内部的可变数量的输入参数:
在python中,我定义了一个函数
def py_fn1(a):
return 2 * a
def py_fn2(a, b):
return a+b
def call_fn_py(fn, *args):
return fn(*args)
a = call_fn_py(py_fn1, 15) # returns 30
b = call_fn_py(py_fn2, 10, 11) # returns 21根据注释给出结果。我希望使用boost python在C++中实现C++(fn,*args)。到目前为止,我已经:
using namespace boost::python;
object call_fn(object fn, tuple arg_in)
{
return fn(arg_in);
}
BOOST_PYTHON_MODULE(python_addins)
{
using namespace boost::python;
def("call_fn", &call_fn);
}但之后做的事情如下:
import python_addins
d = python_addins.call_fn(py_fn1, (5,)) # returns (5,5)这不是我想要的。我怎样才能写call_fn来表现得像call_fn_py?
谢谢,马克
发布于 2012-08-16 22:45:19
可以使用可变数量的参数调用python函数。有两种方法:
call_fn函数来模拟变量数。第一种方法对于一般的C++编程是相当常见的。它需要创建一组重载函数,这些函数根据参数的数量而有所不同:call_fn( fn )、call_fn( fn, A1 )、call_fn( fn, A1, ...An)。使用C++11可变模板函数可以减少样板代码的数量。但是,在定义包装器时,必须指定模板函数的确切类型。因此,这种方法将限制基于模板实例化包装的参数的数量。
#include <boost/python.hpp>
using boost::python;
object call_fn1( object fn, object a1 )
{
return fn( a1 );
}
object call_fn2( object fn, object a1, object a2 )
{
return fn( a1, a2 );
}
object call_fn3( object fn, object a1, object a2, object a3 )
{
return fn( a1, a2, a3 );
}
BOOST_PYTHON_MODULE(example)
{
def( "call_fn", &call_fn1 );
def( "call_fn", &call_fn2 );
def( "call_fn", &call_fn3 );
}下面是一个演示:
>>> def py_fn1( a ): return 2 * a
...
>>> def py_fn2( a, b ): return a + b
...
>>> def call_fn_py( fn, *args ):
... from example import call_fn
... return call_fn( fn, *args )
...
>>> call_fn_py( py_fn1, 15 )
30
>>> call_fn_py( py_fn2, 10, 11 )
21第二种方法利用元组。它要求调用方将参数打包到元组中,而调用函数则需要将参数解压缩。但是,由于在python中进行元组打包和解压缩更容易,所以可以在python中对example.call_fn进行修补,这样函数参数就可以用助手函数来修饰,该函数函数在委派之前解包参数。
在C++中,创建接受单个boost::python::tuple参数的call_fn函数。
#include <boost/python.hpp>
using namespace boost::python;
object call_fn( object fn, tuple args )
{
return fn( args );
}
BOOST_PYTHON_MODULE(example)
{
def( "call_fn", &call_fn );
}现在,创建将修补example_ext.py的example.call_fn
import example
def patch_call_fn():
# Store handle to unpatched call_fn.
original = example.call_fn
# Helper function to create a closure that unpacks arguments
# before delegating to the user function.
def unpack_args( fn ):
def wrapper( args ):
return fn( *args )
return wrapper
# The patched function that will wrap the user function.
def call_fn( fn, *args ):
return original( unpack_args( fn ), args )
return call_fn
# Patch example.
example.call_fn = call_fn = patch_call_fn()可以使用同样的演示,唯一需要的更改是需要导入example_ext而不是example。
>>> def py_fn1( a ): return 2 * a
...
>>> def py_fn2( a, b ): return a + b
...
>>> def call_fn_py( fn, *args ):
... from example_ext import call_fn
... return call_fn( fn, *args )
...
>>> call_fn_py( py_fn1, 15 )
30
>>> call_fn_py( py_fn2, 10, 11 )
21https://stackoverflow.com/questions/11904015
复制相似问题