[英]How to expose a c++ function taking variable arguments in boost python
[英]calling a Python function with variable number of input arguments from boost python
是否可以從boost :: python內部調用具有可變數量的輸入參數的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 ++中實現call_fn(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?
謝謝馬克
可以使用可變數量的參數來調用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 ++中,創建一個call_fn
函數,該函數接受單個boost::python::tuple
參數。
#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 )
21
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.