首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >当将Cython扩展与Windows上的C库链接时,“未解析的外部符号”-error

当将Cython扩展与Windows上的C库链接时,“未解析的外部符号”-error
EN

Stack Overflow用户
提问于 2020-09-05 02:57:10
回答 1查看 1.8K关注 0票数 4

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

我使用VS 2019创建了mylib.libsetup.py来构建Cython(有关详细信息和代码,请参阅下面的代码),但是链接器出现了错误:

错误LNK2001:未解析的外部符号hello

然而,当我运行我在其他帖子中找到的nm mylib.lib时,我可以看到符号_hello是存在的:

代码语言:javascript
复制
D:\Codes\git_folders\my_repository\Cython_test\lib>nm mylib.lib
...
Debug/examples.obj:
...
00000000 T _hello
...

出什么问题了?

代码:

pyexamples.pyx

代码语言:javascript
复制
cdef extern from "examples.h":
    void hello(const char *name)

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

setup.py

代码语言:javascript
复制
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

代码语言:javascript
复制
#include <stdio.h>
#include "examples.h"

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

examples.h

代码语言:javascript
复制
#ifndef EXAMPLES_H
#define EXAMPLES_H

void hello(const char *name);

#endif

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

我犯了这个错误。

代码语言:javascript
复制
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这个名字。

代码语言:javascript
复制
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

代码语言:javascript
复制
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中将“活动解决方案平台”更改为x64 )之后,这里是dumpbin /symbols mylib.lib的结果。我可以在总结中看到hello函数。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-09-05 19:16:52

为x64重新构建(静态)库。

库中的符号名为_hello,而不是x64构建时所期望的hello (您的扩展名为64位,如日志中所示)。

在x64上,MSVC在编译为C代码时不会损坏名称,因此产生的符号是简单的- hello,但是它在x86 (这里的文件这里有一个例子 On godbolt.org)上使用mangle名称:

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

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

如果库是dll,则符号的名称将略有不同。呼叫

代码语言:javascript
复制
__declspec( dllimport ) void hello(char* a);

将导致(现场直播 on godbolt.org):

  • __imp__hello ( imphello之间的两个下划线)用于x86 /32位,即declspec(dllimport)的前缀__imp_和x86上__cdecl的名称损坏导致的前缀_
  • __imp_hello ( imphello之间的下划线)用于x64/64位,也就是说,由于declspec(dllimport),只有前缀__imp_

还有一种更直接的方法可以看到,库是32位,方法是运行:

代码语言:javascript
复制
dumpbin /headers mylibrary.lib

它将为32位构建生成machine (x86)

代码语言:javascript
复制
...
File Type: LIBRARY

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

但是64位构建的machine (x64)

代码语言:javascript
复制
...
File Type: LIBRARY

FILE HEADER VALUES
            8664 machine (x64)

此外,MSVC-链接器用于在机器不匹配时生成警告:

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

不知道为什么它不在你的日志里。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/63750020

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档