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

Cython嵌入Python至C程序:链接embed.o失败求助

链接嵌入Python的C程序时出现未定义引用错误

问题详情

我是刚接触将Python源码嵌入C程序的新手,编写了基础程序创建名为introduction的Cython模块,模块包含同名函数:

cdef char* introduction(char* name, char* lastName):
    return "Hello, {} {}!".format(name, lastName).encode("utf-8")

随后编写了如下C程序调用该模块:

/**
File            :   embed.c
Project         :   None
Programmer      :   Braiden Gole
First version   :   2023-04-22
Description     :   This is my first embeded python program.

NOTE: Where Python is located.
NOTE: C:\Users\<my_username>\AppData\Local\Programs\Python\Python311\include
NOTE: "C:\Users\<my_username>\AppData\Local\Programs\Python\Python311\libs\python311.lib"
NOTE: "C:\Users\<my_username>\AppData\Local\Programs\Python\Python311\python311.dll"

COMPILE:
gcc -c embed.c -o embed.o -IC:/Users/<my_username>/AppData/Local/Programs/Python/Python311/include
LINK:
gcc -o embed embed.o -IC:/Users/<my_username>/AppData/Local/Programs/Python/Python311/include -LC:/Users/<my_username>/AppData/Local/Programs/Python/Python311/libs -lpython311
*/
#include <stdio.h>
#include <Python.h>

int main(int argc, char* argv[])
{   
    // Initialize the python interpreter.
    Py_Initialize();

    // Import the CPython module.
    PyObject* pModule = PyImport_ImportModule("introduction");
    if (!pModule)
    {
        printf("%s", "Failed to imprt python module.");
        return 1;
    }

    PyObject* pFunction = PyObject_GetAttrString(pModule, "introduction");

    if (!pFunction || !PyCallable_Check(pFunction))
    {
        printf("%s", "Failed to get python function.");
        return 1;
    }

    // Create a tuple and set the arguments of the function.
    PyObject* pArguments = PyTuple_New(2);
    PyTuple_SetItem(pArguments, 0, PyUnicode_FromString("Braiden"));
    PyTuple_SetItem(pArguments, 1, PyUnicode_FromString("Gole"));

    PyObject* pResult = PyObject_CallObject(pFunction, pArguments);
    Py_DECREF(pArguments);

    if (!pResult)
    {
        printf("%s", "Failed to call python function.");
        return 1;
    }

    char* introduction = PyBytes_AsString(pResult);
    printf("%s", introduction);
    Py_DECREF(pResult);

    // Clean up resources.
    Py_DECREF(pFunction);
    Py_DECREF(pModule);
    Py_Finalize();
    return 0;
}

注释中的路径为系统实际路径,已确认目录和文件均存在。可以成功编译embed.c,但无法链接目标文件embed.o。

环境说明

  • Python已添加至PATH
  • 已安装Python调试符号
  • 已安装Python调试二进制文件
  • 当前使用Python 3.11.3,曾尝试链接Python 3.10,问题依旧

链接错误信息

c:/mingw/bin/../lib/gcc/mingw32/9.2.0/../../../../mingw32/bin/ld.exe: embed.o:embed.c:(.text+0x23): undefined reference to `_imp___Py_Dealloc'
c:/mingw/bin/../lib/gcc/mingw32/9.2.0/../../../../mingw32/bin/ld.exe: embed.o:embed.c:(.text+0x3b): undefined reference to `_imp__Py_Initialize'
c:/mingw/bin/../lib/gcc/mingw32/9.2.0/../../../../mingw32/bin/ld.exe: embed.o:embed.c:(.text+0x49): undefined reference to `_imp__PyImport_ImportModule'
c:/mingw/bin/../lib/gcc/mingw32/9.2.0/../../../../mingw32/bin/ld.exe: embed.o:embed.c:(.text+0x88): undefined reference to `_imp__PyObject_GetAttrString'
c:/mingw/bin/../lib/gcc/mingw32/9.2.0/../../../../mingw32/bin/ld.exe: embed.o:embed.c:(.text+0xa1): undefined reference to `_imp__PyCallable_Check'
c:/mingw/bin/../lib/gcc/mingw32/9.2.0/../../../../mingw32/bin/ld.exe: embed.o:embed.c:(.text+0xd1): undefined reference to `_imp__PyTuple_New'
c:/mingw/bin/../lib/gcc/mingw32/9.2.0/../../../../mingw32/bin/ld.exe: embed.o:embed.c:(.text+0xe3): undefined reference to `_imp__PyUnicode_FromString'
c:/mingw/bin/../lib/gcc/mingw32/9.2.0/../../../../mingw32/bin/ld.exe: embed.o:embed.c:(.text+0xfd): undefined reference to `_imp__PyTuple_SetItem'
c:/mingw/bin/../lib/gcc/mingw32/9.2.0/../../../../mingw32/bin/ld.exe: embed.o:embed.c:(.text+0x10b): undefined reference to `_imp__PyUnicode_FromString'
c:/mingw/bin/../lib/gcc/mingw32/9.2.0/../../../../mingw32/bin/ld.exe: embed.o:embed.c:(.text+0x125): undefined reference to `_imp__PyTuple_SetItem'
c:/mingw/bin/../lib/gcc/mingw32/9.2.0/../../../../mingw32/bin/ld.exe: embed.o:embed.c:(.text+0x13b): undefined reference to `_imp__PyObject_CallObject'
c:/mingw/bin/../lib/gcc/mingw32/9.2.0/../../../../mingw32/bin/ld.exe: embed.o:embed.c:(.text+0x17b): undefined reference to `_imp__PyBytes_AsString'
c:/mingw/bin/../lib/gcc/mingw32/9.2.0/../../../../mingw32/bin/ld.exe: embed.o:embed.c:(.text+0x1be): undefined reference to `_imp__Py_Finalize'
collect2.exe: error: ld returned 1 exit status

解决方法

1. 生成MinGW兼容的Python静态库

Windows官方Python是用MSVC编译的,MinGW无法直接链接其提供的.lib文件,需要生成MinGW可用的.a库:

  • 下载gendef工具(通常随MinGW或单独提供)
  • 进入Python的dll所在目录(C:\Users\<my_username>\AppData\Local\Programs\Python\Python311)
  • 执行以下命令生成.def文件和.a库:
gendef python311.dll
dlltool -D python311.dll -d python311.def -l libpython311.a
  • 将生成的libpython311.a复制到Python的libs目录下

2. 调整链接命令

链接时确保-lpython311放在目标文件之后,并且指定正确的库路径:

gcc -o embed embed.o -IC:/Users/<my_username>/AppData/Local/Programs/Python/Python311/include -LC:/Users/<my_username>/AppData/Local/Programs/Python/Python311/libs -lpython311

如果.a库在当前目录,添加-L.参数。

3. 匹配编译位数与宏定义

  • 确保MinGW的位数和Python一致(32位MinGW对应32位Python,64位对应64位)
  • 编译时添加对应宏定义:
    32位Python:
    gcc -c embed.c -o embed.o -IC:/Users/<my_username>/AppData/Local/Programs/Python/Python311/include -DMS_WIN32
    
    64位Python:
    gcc -c embed.c -o embed.o -IC:/Users/<my_username>/AppData/Local/Programs/Python/Python311/include -DMS_WIN64
    

4. 其他注意事项

  • 确保Python的python311.dll所在目录已加入系统PATH,或者将dll复制到生成的可执行文件同目录下
  • 运行程序前,确保introduction模块所在目录在Python的搜索路径中(可通过设置PYTHONPATH环境变量)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 21:37:41