在Windows上将Cython扩展链接到C库时出现“无法解析的外部符号”错误

皮革

我正在学习Cython,并尝试运行一个简单的示例,在这里:使C库可调用

我使用VS 2019创建mylib.libsetup.py构建Cython扩展(有关详细信息和代码,请参见下文),但是链接器失败并出现错误:

错误LNK2001:无法解析的外部符号

但是,当我nm mylib.lib在其他帖子中找到自己的跑步时,可以看到该符号_hello存在:

D:\Codes\git_folders\my_repository\Cython_test\lib>nm mylib.lib
...
Debug/examples.obj:
...
00000000 T _hello
...

怎么了?


码:

pyexamples.pyx

cdef extern from "examples.h":
    void hello(const char *name)

def py_hello(name: bytes) -> None:
    hello(name)

setup.py

from distutils.core import setup
from distutils.extension import Extension
from Cython.Build import cythonize

examples_extension = Extension(
    name="pyexamples",
    sources=["pyexamples.pyx"],
    libraries=["mylib"],
    library_dirs=["lib"],
    include_dirs=["lib"]
)
setup(
    name="pyexamples",
    ext_modules=cythonize([examples_extension])
)

examples.c

#include <stdio.h>
#include "examples.h"

void hello(const char *name) {
    printf("hello %s\n", name);
}

examples.h

#ifndef EXAMPLES_H
#define EXAMPLES_H

void hello(const char *name);

#endif

但是,如果我运行此命令, python setup.py build_ext --inplace

我得到这个错误。

running build_ext
building 'pyexamples' extension
C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.27.29110\bin\HostX86\x64\cl.exe /c /nologo /Ox /W3 /GL /DNDEBUG /MD -Ilib -IC:\Users\swsyo\anaconda3\include -IC:\Users\swsyo\anaconda3\include "-IC:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.27.29110\ATLMFC\include" "-IC:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.27.29110\include" "-IC:\Program Files (x86)\Windows Kits\10\include\10.0.18362.0\ucrt" "-IC:\Program Files (x86)\Windows Kits\10\include\10.0.18362.0\shared" "-IC:\Program Files (x86)\Windows Kits\10\include\10.0.18362.0\um" "-IC:\Program Files (x86)\Windows Kits\10\include\10.0.18362.0\winrt" "-IC:\Program Files (x86)\Windows Kits\10\include\10.0.18362.0\cppwinrt" /Tcpyexamples.c /Fobuild\temp.win-amd64-3.7\Release\pyexamples.obj
pyexamples.c
C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.27.29110\bin\HostX86\x64\link.exe /nologo /INCREMENTAL:NO /LTCG /DLL /MANIFEST:EMBED,ID=2 /MANIFESTUAC:NO /LIBPATH:lib /LIBPATH:C:\Users\swsyo\anaconda3\libs /LIBPATH:C:\Users\swsyo\anaconda3\PCbuild\amd64 "/LIBPATH:C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.27.29110\ATLMFC\lib\x64" "/LIBPATH:C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.27.29110\lib\x64" "/LIBPATH:C:\Program Files (x86)\Windows Kits\10\lib\10.0.18362.0\ucrt\x64" "/LIBPATH:C:\Program Files (x86)\Windows Kits\10\lib\10.0.18362.0\um\x64" mylib.lib /EXPORT:PyInit_pyexamples build\temp.win-amd64-3.7\Release\pyexamples.obj /OUT:D:\git_folders\my_repository\Cython_test\pyexamples.cp37-win_amd64.pyd /IMPLIB:build\temp.win-amd64-3.7\Release\pyexamples.cp37-win_amd64.lib
   Creating library build\temp.win-amd64-3.7\Release\pyexamples.cp37-win_amd64.lib and object build\temp.win-amd64-3.7\Release\pyexamples.cp37-win_amd64.exp
pyexamples.obj : error LNK2001: unresolved external symbol hello
D:\git_folders\my_repository\Cython_test\pyexamples.cp37-win_amd64.pyd : fatal error LNK1120: 1 unresolved externals
error: command 'C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Community\\VC\\Tools\\MSVC\\14.27.29110\\bin\\HostX86\\x64\\link.exe' failed with exit status 1120

更多细节:

基于以下注释,我运行dumpbin mylib.lib命令以查看hello函数是否在库中。这是正确的方法吗?hello在此摘要中看不到该名称

D:\Codes\git_folders\my_repository\Cython_test\lib>dumpbin mylib.lib
Microsoft (R) COFF/PE Dumper Version 14.27.29111.0
Copyright (C) Microsoft Corporation.  All rights reserved.


Dump of file mylib.lib

File Type: LIBRARY

  Summary

          E8 .chks64
         C94 .debug$S
          C8 .debug$T
         10A .drectve
           5 .msvcjmc
           A .rdata
           8 .rtc$IMZ
           8 .rtc$TMZ
         1B4 .text$mn

我还跑nm mylib.lib了我在其他帖子中找到的。您可以_hello在摘要末尾看到

D:\Codes\git_folders\my_repository\Cython_test\lib>nm mylib.lib

Debug\mylib.obj:
00000000 N .chks64
00000000 N .debug$S
00000000 N .debug$S
00000000 N .debug$S
00000000 N .debug$T
00000000 i .drectve
00000000 d .msvcjmc
00000000 r .rtc$IMZ
00000000 r .rtc$TMZ
00000000 t .text$mn
00000000 t .text$mn
         U @__CheckForDebuggerJustMyCode@4
010471b7 a @comp.id
80000391 a @feat.00
00000000 d __87B4E6C0_mylib@c
00000000 T __JustMyCode_Default
         U __RTC_CheckEsp
         U __RTC_InitBase
00000000 r __RTC_InitBase.rtc$IMZ
         U __RTC_Shutdown
00000000 r __RTC_Shutdown.rtc$TMZ
00000000 T _fnmylib

Debug/examples.obj:
00000000 N .chks64
00000000 N .debug$S
00000000 N .debug$S
00000000 N .debug$S
00000000 N .debug$S
00000000 N .debug$S
00000000 N .debug$S
00000000 N .debug$T
00000000 i .drectve
00000000 d .msvcjmc
00000000 r .rdata
00000000 r .rtc$IMZ
00000000 r .rtc$TMZ
00000000 t .text$mn
00000000 t .text$mn
00000000 t .text$mn
00000000 t .text$mn
00000000 t .text$mn
00000000 R ??_C@_09DEHHIH@hello?5?$CFs?6@
00000008 C ?_OptionsStorage@?1??__local_stdio_printf_options@@9@9
         U @__CheckForDebuggerJustMyCode@4
010471b7 a @comp.id
80000391 a @feat.00
00000000 T ___local_stdio_printf_options
00000001 d __101834BA_corecrt_wstdio@h
00000003 d __2F33A99E_examples@c
00000002 d __AD6A91B7_stdio@h
00000000 d __F66CEB67_corecrt_stdio_config@h
         U __imp____acrt_iob_func
         U __imp____stdio_common_vfprintf
00000000 T __JustMyCode_Default
         U __RTC_CheckEsp
         U __RTC_InitBase
00000000 r __RTC_InitBase.rtc$IMZ
         U __RTC_Shutdown
00000000 r __RTC_Shutdown.rtc$TMZ
00000000 T __vfprintf_l
00000000 T _hello
00000000 T _printf

在为x64系统重建项目后(必须在Build> Configuration Manager中将“活动解决方案平台”更改为x64),这是的结果dumpbin /symbols mylib.lib我可以hello在摘要中看到该功能。

在此处输入图片说明

ad

重建x64的(静态)库。

库中的符号被调用,_hello而不是hellox64构建所期望的符号(如日志中所示,您的扩展是针对64位构建的)。

在x64上,MSVC在编译为C代码时不会更改名称,因此生成的符号很简单- hello,但在x86上却可以更改C名称(此处为文档此处为godbolt.org上的示例):

  • __cdecl调用约定(如果不使用特殊的编译标志,则为x86的默认设置)为_名称添加前缀,这将导致符号被调用_hello
  • __stdcall-调用约定(如果使用编译/Gz或明确指定了调用约定,即void __stdcall hello(char *)_在名称和名称后缀中@加上参数列表中的字节数,即会导致_hello@4

因此,很明显,您的库是32位构建的,因此无法链接到64位dll。


如果库是一个dll,则符号的名称会稍有不同。呼唤

__declspec( dllimport ) void hello(char* a);

会导致(请参见godbolt.org上的直播):

  • __imp__hello对于x86 / 32位,imp之间有两个下划线hello),即由于x86上的名称改写而导致的前缀因名称改写__imp_而导致的declspec(dllimport)前缀___cdecl
  • __imp_hello对于x64 / 64位,则imp之间一个下划线hello),即仅前缀__imp_declspec(dllimport)

还有一种更直接的方法,通过运行以下命令可以看到该库是32位的:

dumpbin /header mylibrary.lib

这将产生machine (x86)32位版本:

...
File Type: LIBRARY

FILE HEADER VALUES
             14C machine (x86)
...

machine (x64)对于64位版本:

...
File Type: LIBRARY

FILE HEADER VALUES
            8664 machine (x64)

此外,当机器不匹配时,MSVC链接器还用于发出警告:

mylibrary.lib:警告LNK4272:库机器类型“ X86”与目标机器类型“ x64”冲突

不知道为什么它不在您的日志中。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

与OpenCV 3.0链接时出现“无法解析的外部符号”错误

来自分类Dev

使用名称空间链接到静态库时,无法解析的外部符号

来自分类Dev

使用CImg库时出现无法解决的外部符号错误

来自分类Dev

LNK2019错误(无法解析的外部符号)将SQLite链接到DLL

来自分类Dev

在运行时动态加载库时出现“未解析的外部符号”错误

来自分类Dev

错误LNK2019:将代码放入cpp文件时出现无法解析的外部符号

来自分类Dev

错误LNK2019:使用SendInput()时出现无法解析的外部符号

来自分类Dev

链接:错误LNK2001:无法解析的外部符号NtProcessStartup

来自分类Dev

链接:错误LNK2001:无法解析的外部符号NtProcessStartup

来自分类Dev

链接静态库时对未解析的符号强制错误

来自分类Dev

链接器错误:正式包含库时,未解析的符号

来自分类Dev

无法解析的外部符号构建Python C扩展

来自分类Dev

Visual Studio 2012错误LNK2019:无法解析的外部符号,与正在运行的静态库链接

来自分类Dev

与外部库链接时出现GCC“多个定义”错误

来自分类Dev

在Linux上将共享库与未解析的符号链接

来自分类Dev

在Windows上编译GDAL 1.11.0时无法解析的外部符号

来自分类Dev

在Windows上将Python链接到我的C ++代码中-链接器错误

来自分类Dev

SDL构建系统-当我链接到`gnustl_shared`时,在运行时出现“错误:无法加载库:...”

来自分类Dev

C ++ LNK2019错误:无法解析的外部符号

来自分类Dev

POLINK:错误:无法解析的外部符号。佩莱斯C

来自分类Dev

C ++错误LNK2001:无法解析的外部符号

来自分类Dev

在Windows上编译/链接时,CGAL无法解析的外部

来自分类Dev

为什么在链接到库时却出现错误,而在构建库时却没有?

来自分类Dev

在Windows上将符号链接添加到存储库

来自分类Dev

如何在Windows上将OpenCV库正确链接到Eclipse?

来自分类Dev

如何在Windows上将OpenCV库正确链接到Eclipse?

来自分类Dev

使用mex编译.C文件包含库-错误LNK2019:无法解析的外部符号-用于NPTrackingTools

来自分类Dev

访问符号链接时出现错误403

来自分类Dev

链接到poco时,出现RegularExpression错误

Related 相关文章

  1. 1

    与OpenCV 3.0链接时出现“无法解析的外部符号”错误

  2. 2

    使用名称空间链接到静态库时,无法解析的外部符号

  3. 3

    使用CImg库时出现无法解决的外部符号错误

  4. 4

    LNK2019错误(无法解析的外部符号)将SQLite链接到DLL

  5. 5

    在运行时动态加载库时出现“未解析的外部符号”错误

  6. 6

    错误LNK2019:将代码放入cpp文件时出现无法解析的外部符号

  7. 7

    错误LNK2019:使用SendInput()时出现无法解析的外部符号

  8. 8

    链接:错误LNK2001:无法解析的外部符号NtProcessStartup

  9. 9

    链接:错误LNK2001:无法解析的外部符号NtProcessStartup

  10. 10

    链接静态库时对未解析的符号强制错误

  11. 11

    链接器错误:正式包含库时,未解析的符号

  12. 12

    无法解析的外部符号构建Python C扩展

  13. 13

    Visual Studio 2012错误LNK2019:无法解析的外部符号,与正在运行的静态库链接

  14. 14

    与外部库链接时出现GCC“多个定义”错误

  15. 15

    在Linux上将共享库与未解析的符号链接

  16. 16

    在Windows上编译GDAL 1.11.0时无法解析的外部符号

  17. 17

    在Windows上将Python链接到我的C ++代码中-链接器错误

  18. 18

    SDL构建系统-当我链接到`gnustl_shared`时,在运行时出现“错误:无法加载库:...”

  19. 19

    C ++ LNK2019错误:无法解析的外部符号

  20. 20

    POLINK:错误:无法解析的外部符号。佩莱斯C

  21. 21

    C ++错误LNK2001:无法解析的外部符号

  22. 22

    在Windows上编译/链接时,CGAL无法解析的外部

  23. 23

    为什么在链接到库时却出现错误,而在构建库时却没有?

  24. 24

    在Windows上将符号链接添加到存储库

  25. 25

    如何在Windows上将OpenCV库正确链接到Eclipse?

  26. 26

    如何在Windows上将OpenCV库正确链接到Eclipse?

  27. 27

    使用mex编译.C文件包含库-错误LNK2019:无法解析的外部符号-用于NPTrackingTools

  28. 28

    访问符号链接时出现错误403

  29. 29

    链接到poco时,出现RegularExpression错误

热门标签

归档