如何用boost::python从C++暴露带可变参数的Python风格函数?
使用Boost.Python暴露含混合参数类型的C++函数
完全可以实现你要的函数原型,Boost.Python的raw_function支持通过指定强制位置参数数量,来拆分固定参数、可变位置参数和可变关键字参数。以下是具体实现方案:
一、暴露带固定参数+*args+**kwargs的函数
针对你给出的test_kwargs_bis(int i, py::tuple args, py::dict kwargs),只需在暴露时给raw_function传入第二个参数,指定强制位置参数的个数(这里是1),Boost.Python会自动将前1个参数解析为int i,剩余位置参数打包为args,关键字参数打包为kwargs。
C++实现代码
#include <boost/python.hpp> #include <iostream> namespace py = boost::python; py::object test_kwargs_bis(int i, py::tuple args, py::dict kwargs) { std::cout << "固定参数i: " << i << std::endl; std::cout << "可变位置参数数量: " << py::len(args) << std::endl; for (int j = 0; j < py::len(args); ++j) { std::cout << "args[" << j << "]: " << py::extract<int>(args[j]) << std::endl; } std::cout << "可变关键字参数数量: " << py::len(kwargs) << std::endl; py::list keys = kwargs.keys(); for (int j = 0; j < py::len(keys); ++j) { std::string key = py::extract<std::string>(keys[j]); int value = py::extract<int>(kwargs[key]); std::cout << key << ": " << value << std::endl; } return py::object(); } BOOST_PYTHON_MODULE(MyModule) { // 第二个参数1表示强制要求1个位置参数 py::def("test_kwargs_bis", py::raw_function(&test_kwargs_bis, 1)); }
Python测试调用
import MyModule # 调用示例:i=10,args=(20,30),kwargs={"x":1,"y":2} MyModule.test_kwargs_bis(10, 20, 30, x=1, y=2)
二、模拟Python的def f(a,b,c=0,*args,**kwargs)
要实现含必填参数、可选参数、可变位置/关键字参数的完整原型,可结合raw_function的参数指定和默认参数处理:
C++实现代码
#include <boost/python.hpp> #include <iostream> namespace py = boost::python; py::object f(int a, int b, py::object c, py::tuple args, py::dict kwargs) { // 处理可选参数c的默认值:若Python未传,c为None,设为0 int c_val = c.is_none() ? 0 : py::extract<int>(c); std::cout << "必填参数a: " << a << std::endl; std::cout << "必填参数b: " << b << std::endl; std::cout << "可选参数c: " << c_val << std::endl; // 遍历可变位置参数 std::cout << "可变位置参数: "; for (int j = 0; j < py::len(args); ++j) { std::cout << py::extract<int>(args[j]) << " "; } std::cout << std::endl; // 遍历可变关键字参数 std::cout << "可变关键字参数: "; py::list keys = kwargs.keys(); for (int j = 0; j < py::len(keys); ++j) { std::string key = py::extract<std::string>(keys[j]); int value = py::extract<int>(kwargs[key]); std::cout << key << "=" << value << " "; } std::cout << std::endl; return py::object(); } BOOST_PYTHON_MODULE(MyModule) { // 2表示强制2个必填位置参数(a,b),通过py::arg给c设置默认值None py::def("f", py::raw_function(&f, 2), (py::arg("a"), py::arg("b"), py::arg("c")=py::object())); }
Python测试调用
import MyModule # 不传c,使用默认值0 MyModule.f(1, 2, 4, 5, name="test", value=100) # 传入c=30 MyModule.f(10, 20, 30, 40, 50, foo=1, bar=2)
核心要点
raw_function(func, n)中的n是必须传入的位置参数数量,Boost.Python会自动拆分前n个参数为C++函数的固定参数,剩余位置参数打包为tuple,关键字参数打包为dict。- 可选参数通过
py::arg设置默认值为py::object()(对应Python的None),在C++函数内判断并赋予业务默认值即可。
内容的提问来源于stack exchange,提问作者IMas
相关产品推荐
相关产品推荐

