如何使用nanobind为扩展添加可独立导入的子模块?
在nanobind中实现可独立导入的子扩展模块
你要实现import my_ext.sub_ext的导入方式,在nanobind里可以用类似Boost.Python的思路,核心是借助Python的PyImport_AddModule创建子模块,再通过nanobind的接口完成挂载和作用域切换,具体实现如下:
完整代码示例
#include <nanobind/nanobind.h> #include <Python.h> namespace nb = nanobind; // 示例子模块类 class MySubClass { public: void some_method() { /* 自定义逻辑 */ } }; NB_MODULE(my_ext, m) { // 1. 创建或获取子模块 my_ext.sub_ext PyObject *sub_mod = PyImport_AddModule("my_ext.sub_ext"); if (!sub_mod) { nb::raise_import_error("无法创建子模块 my_ext.sub_ext"); return; } // 2. 将Python模块对象包装为nanobind的module实例(标记为借用,避免重复释放) nb::module_ sub_ext(sub_mod, nb::borrowed_t{}); // 3. 将子模块挂载到主模块,让Python能识别my_ext.sub_ext m.attr("sub_ext") = sub_ext; // 4. 切换默认作用域到子模块(可选,后续无指定模块的定义会自动归属子模块) nb::scope guard = sub_ext; // 5. 在子模块中定义类、函数等组件 nb::class_<MySubClass>(sub_ext, "MySubClass") .def(nb::init<>()) .def("some_method", &MySubClass::some_method); // 也可以不切换作用域,直接在定义时指定子模块,效果一致: // nb::def(sub_ext, "sub_func", []() { /* 自定义函数逻辑 */ }); }
关键步骤说明
PyImport_AddModule:和Boost.Python中的作用完全一致,负责获取已存在的子模块或创建新模块,返回的是Python层面的模块对象。nb::module_包装:用nb::borrowed_t标记是借用的对象,告诉nanobind不要管理这个对象的生命周期,避免内存错误。- 挂载子模块:通过
m.attr("sub_ext") = sub_ext把创建好的子模块绑定到主模块的属性上,这样Python既可以通过from my_ext import sub_ext访问,也支持直接import my_ext.sub_ext。 - 作用域切换:
nb::scope guard = sub_ext会把当前默认的定义作用域切换到子模块,后续如果省略模块参数(比如nb::def("func", ...)),元素会自动归到子模块里;如果不想切换作用域,直接在定义时把sub_ext作为第一个参数传入即可。
内容的提问来源于stack exchange,提问作者got here
相关产品推荐
相关产品推荐

