gpt4 book ai didi

python - "unresolved external symbol"- 在 Windows 上将 Cython 扩展链接到 C 库时出错

转载 作者:行者123 更新时间:2023-12-03 11:11:40 26 4
gpt4 key购买 nike

我正在学习 Cython 并尝试运行一个在这里找到的简单示例:making C library callable .
我使用 VS 2019 创建 mylib.libsetup.py构建 Cython 扩展(有关详细信息和代码,请参见下文),但是链接器失败并显示错误:

error LNK2001: unresolved external symbol hello


然而当我跑 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 中将“Active solution platform”更改为 x64),这是 dumpbin /symbols mylib.lib 的结果.我可以看到 hello摘要中的功能。
enter image description here

最佳答案

为 x64 重建(静态)库。
您库中的符号名为 _hello而不是 hello正如人们对 x64 构建所期望的那样(您的扩展是为 64 位构建的,如日志中所示)。
在 x64 上,MSVC 在编译为 C 代码时不会破坏名称,因此结果符号很简单 - hello ,但它确实破坏了 x86 上的 C 名称(here documentationhere an example 在 Godbolt.org 上):

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

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

    如果库是 dll,符号的名称会略有不同。打电话
    __declspec( dllimport ) void hello(char* a);
    会导致( see live on Godbolt.org):
  • __imp__hello (imphello 之间的两个下划线)用于 x86/32 位,即前缀 __imp_由于 declspec(dllimport)和前缀 _由于 __cdecl 的名称修改在 x86 上。
  • __imp_hello (一个下划线介于 imphello 之间)适用于 x64/64 位,即只有前缀 __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-linker 用于产生警告:

    mylibrary.lib : warning LNK4272: library machine type 'X86' conflictswith target machine type 'x64'


    不知道为什么它没有出现在您的日志中。

    关于python - "unresolved external symbol"- 在 Windows 上将 Cython 扩展链接到 C 库时出错,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63750020/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com