You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 17:42:37