【问题标题】:Cython DLL extension compilation using WINAPI fails during linking with error LNK2001使用 WINAPI 的 Cython DLL 扩展编译在链接期间失败并出现错误 LNK2001
【发布时间】:2022-01-03 13:38:14
【问题描述】:

我正在尝试为(Photron)相机驱动程序 DLL 编写 Cython 接口。这个库提供了一个带有头文件的 SDK 和 32 位和 64 位的 Windows 库。我已经在 VisualStudio 中使用这个库成功编译了一个 C++ 示例。另一方面,Cython 编译在链接时失败。

自定义 Cython 代码由一个包含类型的 typedefs.pxd 文件、一个包含来自 SDK 标头的常量和函数声明的 photron.pxd 文件和一个包装器组成camera.pyx 文件中的 cdef 类。

在 setup.py 文件的 Extension(从 setuptools 导入)部分中,我包含了以下部分:

include_dirs=[s.path.abspath(os.path.normpath('./include'))],
libraries=[os.path.join(os.path.abspath(os.curdir), 'Lib', '64bit(x64)', 'PDCLIB')],
library_dirs=[os.path.abspath(os.path.normpath('./Lib/64bit(x64)'))],

我还尝试了 C++ 编译成功的命令行中的标志。 为了让初始 cythonization 步骤正常工作(生成 cpp 文件),我还必须将其添加到 SDK 的标题中:

    #include <windows.h>

以下是 pxd 文件的相关摘录:

from typedefs cimport ulong, uint

cdef extern from "PDCFUNC.h":
    ulong PDC_CloseDevice(ulong nDeviceNo, ulong *pErrorCode)

当我尝试编译代码时,我得到了 cpp 文件,但是当我尝试链接时,对于我在 pxd 文件中声明的每个函数,我得到一系列如下所示的行:

camera.obj : error LNK2001: unresolved external symbol "unsigned long __cdecl PDC_CloseDevice(unsigned long,unsigned long *)" (?PDC_CloseDevice@@YAKKPEAK@Z)

我想这是因为链接器试图在指定的头文件中找到一个 __cdecl 函数,尽管这些函数在头文件中是这样声明的:

unsigned long WINAPI PDC_CloseDevice(unsigned long nDeviceNo, unsigned long *pErrorCode);

由于 Cython 文档明确指出支持调用约定,因此我尝试:

  1. 将 WINAPI 调用约定添加到 pxd 文件,但我在文件的 cythonization 过程中收到 C 变量声明中的语法错误
  2. 直接添加 __stdcall 调用约定,因为无论如何程序都应该以 64 位编译。但是我仍然得到 LNK2001 行来寻找 __cdecl ,就好像 Cython 绕过了调用约定一样。实际上,这是生成的 cpp 文件中的一行:
    __pyx_v_ret = PDC_CloseDevice(__pyx_v_self->device_nb, (&__pyx_v_error_code));

__cdecl 警告也可能是一个红鲱鱼,但我没有其他线索,而且我通常不在 Windows 下编译,所以我对这些工具的了解有限。

【问题讨论】:

  • 链接器没有找到需要的符号。可能库名称或它们的路径是错误的。 libraries 应该只是库的名称(即 PDCLIB),library_dirs 应该是路径(以硬编码名称开头,以确保不会出错)。还要重新检查 python 真的是 64 位而不是 32 位。
  • @ead 我检查了python版本,env确实是64位。 &gt;&gt;&gt; import struct;print( 8 * struct.calcsize("P")) 64 我还检查了library_dirs(并在上面做了os.path.exists)以检查它是否正确。我将库修改为仅名称(尝试小写和大写)无济于事。有趣的是,如果我故意在库名称中引入错字,它会触发 LNK1181 错误,指出它找不到库,如果没有错字就不会发生这种情况。 [这个问题]stackoverflow.com/q/47740418/3324315很接近,但它不起作用。

标签: windows winapi cython linker-errors


【解决方案1】:

在尝试了所有其他方法(包括正确编译的 Visual Studio 项目中的所有选项)后,我重新启动了一个最小示例,pxd 文件中只有以下内容

cdef extern from "PDCLIB.h"
    ulong __stdcall PDC_Init(ulong *pErrorCode)
    ulong __stdcall PDC_CloseDevice(ulong nDeviceNo, ulong *pErrorCode)

还有一个更简单的 pyx 文件,除了扩展名外,同名。

from pyphotron_pdclib cimport *

from typedefs cimport ulong, uint

cpdef init_pdc_lib():
    cdef ulong error_code = 0
    success = PDC_Init(&error_code)
    assert success != 0
    
cpdef close_cam(ulong dev_num):
    cdef ulong error_code = 0
    success = PDC_CloseDevice(dev_num, &error_code)
    assert success != 0

我在编译中看到的主要区别是

  1. 它现在可以在 c 中编译,因为没有更多的扩展类型(cdef 类)
  2. pyx文件与pxd文件同名

安装文件中的编译和链接选项如下:

extra_compile_args=['/Gz', '/fp:precise', '/Zc:wchar_t', '/Zc:forScope', '/Zc:inline'],
extra_link_args=['/DEBUG', '/MACHINE:X64'],

【讨论】:

    猜你喜欢
    • 2018-04-25
    • 2019-10-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多