【发布时间】: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 文档明确指出支持调用约定,因此我尝试:
- 将 WINAPI 调用约定添加到 pxd 文件,但我在文件的 cythonization 过程中收到 C 变量声明中的语法错误。
- 直接添加 __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位。
>>> import struct;print( 8 * struct.calcsize("P")) 64我还检查了library_dirs(并在上面做了os.path.exists)以检查它是否正确。我将库修改为仅名称(尝试小写和大写)无济于事。有趣的是,如果我故意在库名称中引入错字,它会触发 LNK1181 错误,指出它找不到库,如果没有错字就不会发生这种情况。 [这个问题]stackoverflow.com/q/47740418/3324315很接近,但它不起作用。
标签: windows winapi cython linker-errors