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

如何创建包含多个子模块的Python C扩展模块?

Python C扩展单共享库实现子模块方案

核心思路

不需要拆分多个共享库,只需在单个主模块初始化函数中完成以下操作:

  1. 创建主模块对象
  2. 分别创建子模块(subpart1、subpart2)对象
  3. 将子模块对应的类、函数注册到子模块中
  4. 将子模块作为属性添加到主模块
    最终编译为单个共享库,即可实现my_custom_module.subpart1这类语法访问。

完整实现示例

1. C扩展代码(my_custom_module.c)

#include <Python.h>

// -------------------------- subpart1 子模块内容 --------------------------
// ClassB 的类型定义
static PyObject* ClassB_new(PyTypeObject* type, PyObject* args, PyObject* kwds) {
    PyObject* self = type->tp_alloc(type, 0);
    return self;
}

static PyTypeObject ClassBType = {
    PyVarObject_HEAD_INIT(NULL, 0)
    .tp_name = "my_custom_module.subpart1.ClassB",
    .tp_basicsize = sizeof(PyObject),
    .tp_flags = Py_TPFLAGS_DEFAULT,
    .tp_new = ClassB_new,
};

// subpart1 子模块的方法表(可选)
static PyMethodDef Subpart1Methods[] = {
    {"func_b", NULL, METH_VARARGS, "Subpart1 test function"},
    {NULL, NULL, 0, NULL}  // 结束标记
};

// subpart1 子模块定义
static struct PyModuleDef subpart1_module = {
    PyModuleDef_HEAD_INIT,
    .m_name = "my_custom_module.subpart1",
    .m_doc = "Subpart1 module",
    .m_size = -1,
    .m_methods = Subpart1Methods,
};

// -------------------------- subpart2 子模块内容 --------------------------
// ClassC 的类型定义
static PyObject* ClassC_new(PyTypeObject* type, PyObject* args, PyObject* kwds) {
    PyObject* self = type->tp_alloc(type, 0);
    return self;
}

static PyTypeObject ClassCType = {
    PyVarObject_HEAD_INIT(NULL, 0)
    .tp_name = "my_custom_module.subpart2.ClassC",
    .tp_basicsize = sizeof(PyObject),
    .tp_flags = Py_TPFLAGS_DEFAULT,
    .tp_new = ClassC_new,
};

// subpart2 子模块定义
static struct PyModuleDef subpart2_module = {
    PyModuleDef_HEAD_INIT,
    .m_name = "my_custom_module.subpart2",
    .m_doc = "Subpart2 module",
    .m_size = -1,
};

// -------------------------- 主模块初始化 --------------------------
PyMODINIT_FUNC PyInit_my_custom_module(void) {
    PyObject* main_module;
    PyObject* sub1_module;
    PyObject* sub2_module;

    // 1. 创建并初始化主模块
    static struct PyModuleDef main_module_def = {
        PyModuleDef_HEAD_INIT,
        .m_name = "my_custom_module",
        .m_doc = "Main custom module",
        .m_size = -1,
    };
    main_module = PyModule_Create(&main_module_def);
    if (!main_module) goto error;

    // 2. 创建并初始化 subpart1 子模块
    sub1_module = PyModule_Create(&subpart1_module);
    if (!sub1_module) goto error;
    // 将 ClassB 注册到 subpart1
    if (PyType_Ready(&ClassBType) < 0) goto error;
    Py_INCREF(&ClassBType);
    PyModule_AddObject(sub1_module, "ClassB", (PyObject*)&ClassBType);

    // 3. 创建并初始化 subpart2 子模块
    sub2_module = PyModule_Create(&subpart2_module);
    if (!sub2_module) goto error;
    // 将 ClassC 注册到 subpart2
    if (PyType_Ready(&ClassCType) < 0) goto error;
    Py_INCREF(&ClassCType);
    PyModule_AddObject(sub2_module, "ClassC", (PyObject*)&ClassCType);

    // 4. 将子模块添加到主模块
    PyModule_AddObject(main_module, "subpart1", sub1_module);
    PyModule_AddObject(main_module, "subpart2", sub2_module);

    return main_module;

error:
    // 错误清理:减少引用计数并返回 NULL
    Py_XDECREF(main_module);
    Py_XDECREF(sub1_module);
    Py_XDECREF(sub2_module);
    return NULL;
}

2. 编译配置(setup.py)

from setuptools import setup, Extension

setup(
    name="my_custom_module",
    version="0.1",
    ext_modules=[
        Extension(
            "my_custom_module",
            sources=["my_custom_module.c"],
        )
    ]
)

3. 编译与测试

  • 编译安装:执行 pip install . 或 python setup.py install
  • 测试代码:
import my_custom_module

# 访问子模块的类
b_instance = my_custom_module.subpart1.ClassB()
c_instance = my_custom_module.subpart2.ClassC()

print(type(b_instance))  # <class 'my_custom_module.subpart1.ClassB'>
print(type(c_instance))  # <class 'my_custom_module.subpart2.ClassC'>

关键细节说明

  • 子模块的tp_name必须包含完整路径(如my_custom_module.subpart1.ClassB),否则Python会认为类属于主模块
  • 所有子模块的创建和注册逻辑都在PyInit_my_custom_module中完成,最终只生成一个my_custom_module.so(或对应平台的共享库文件)
  • 使用Py_XDECREF进行错误清理,避免内存泄漏

内容的提问来源于stack exchange,提问作者Nicolas V

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 22:45:29