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

Python C扩展导入报错:模块未定义PyInit_library导出函数

解决ImportError: dynamic module does not define module export function (PyInit_library)

你的核心问题出在模块初始化函数的命名不匹配,这是Python C扩展必须遵守的硬性规则:初始化函数的名字必须严格是PyInit_<你的模块名>,其中<你的模块名>要和setup.py里Extension的第一个参数完全一致。


第一步:修复初始化函数名(解决导入报错)

看你的代码:

  • setup.py里定义的模块名是'library':
    module = Extension('library', sources = ['library.c'])
    
  • 但你的C代码里的初始化函数是PyInit_myModule:
    PyMODINIT_FUNC PyInit_myModule(void) {
        Py_Initialize();
        return PyModule_Create(&myModule);
    }
    

这就导致Python加载模块时找不到PyInit_library函数,直接触发报错。把函数名改成PyInit_library,同时注意去掉Py_Initialize()调用——模块加载时Python已经完成初始化了,手动调用会引发问题:

PyMODINIT_FUNC PyInit_library(void) {
    return PyModule_Create(&myModule);
}

第二步:修复其他潜在问题(否则导入后运行会出错)

解决了导入问题后,你的代码还有几个关键bug需要修复:

1. 结构体定义语法错误

你的Library.h里的typedef struct后面多了多余的分号,导致无法直接用Book或Library作为类型名:

// 原错误代码
typedef struct Book {
    char *book_name;
    char *book_type;
    char *book_author;
    int numOfPages;
}; // 这里的分号多余,应该改成} Book;

typedef struct Library {
    struct Book Books[100];
    int booksStored;
}; // 同理,改成} Library;

修正后:

typedef struct Book {
    char *book_name;
    char *book_type;
    char *book_author;
    int numOfPages;
} Book;

typedef struct Library {
    Book Books[100];
    int booksStored;
} Library;

2. 字符串比较逻辑错误

C语言中不能用==比较字符串内容(这只会比较指针地址),必须用strcmp函数(记得包含<string.h>头文件)。同时你还写错了数组元素的访问方式:

// 原错误代码
if (lib->Books->book_name == bkname) {

修正为:

#include <string.h> // 必须添加这个头文件

// ...

if (strcmp(lib->Books[i].book_name, bkname) == 0) {

3. Python参数解析错误

你用了"O&s"格式符,但O&需要配套转换函数才能把Python对象转换成C结构体指针——Python里没有直接对应C结构体的原生对象。这里推荐两种可行的解决思路:

  • 思路一:在C扩展内封装Library结构体
    添加一个创建Library的函数,用PyCapsule封装指针返回给Python,后续函数从胶囊中取出指针:
    static PyObject* create_library(PyObject* self) {
        Library* lib = malloc(sizeof(Library));
        lib->booksStored = 0;
        return PyCapsule_New(lib, "Library", free); // 自动释放内存
    }
    
    然后在myMethods里添加这个函数,解析参数时用O格式符取出胶囊:
    static PyObject* addBook(PyObject* self, PyObject* args) {
        PyObject* capsule;
        char *bookname;
        char * booktype;
        char *bookauthor;
        int numOfPages;
        if (!PyArg_ParseTuple(args, "Osssi", &capsule, &bookname, &booktype, &bookauthor, &numOfPages))
            return NULL;
        Library* lib = PyCapsule_GetPointer(capsule, "Library");
        if (!lib) return NULL;
        // 返回Python布尔值,而不是用错误的"p"格式符
        return PyBool_FromLong(CaddBook(lib, bookname, booktype, bookauthor, numOfPages));
    }
    
  • 思路二:用Python的ctypes定义对应结构体
    在Python代码中用ctypes定义和C一致的结构体,直接传递给扩展函数,这种方式需要调整参数解析逻辑。

4. 返回值构建错误

你用Py_BuildValue("p", CaddBook(...))返回bool值,但"p"是用来处理char*的,会把bool值转换成指针地址,导致Python得到错误结果。应该用PyBool_FromLong返回原生Python布尔值:

return PyBool_FromLong(CaddBook(lib, bookname, booktype, bookauthor, numOfPages));

5. 其他小优化

  • version函数不需要强制转换(PyCFunction),直接写version即可:
    {"version", version, METH_NOARGS, "Returns the version."},
    

最后重新编译

修改完所有代码后,重新执行编译命令:

sudo python3 setup.py build_ext --inplace

现在应该可以正常import library并调用函数了。

内容的提问来源于stack exchange,提问作者Damian Thompson

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 04:10:10