gpt4 book ai didi

python - 在 Windows 中构建 Python C 扩展时导出符号时出错

转载 作者:可可西里 更新时间:2023-11-01 09:47:32 25 4
gpt4 key购买 nike

我正在努力将 Python 模块移植到 Windows。我有一个玩具示例如下。

文件夹结构是:

foo/
libfoo/
foo.c
setup.py

setup.py

from setuptools import setup, Extension

sources = ['libfoo/foo.c']

foo = Extension('libfoo',
sources = sources,
define_macros = None,
include_dirs = ['./libfoo'],
libraries = None,
library_dirs = None,
)

setup(name = 'foo',
ext_modules = [foo],
install_requires = ['setuptools'],
)

libfoo/foo.c(为了完整性)

#include <stdio.h>

void foo() {
printf("Hello World!");
}

当我尝试安装软件包时遇到错误。

C:\Users\user\foo>python setup.py install
running install
running bdist_egg
running egg_info
creating foo.egg-info
writing requirements to foo.egg-info\requires.txt
writing foo.egg-info\PKG-INFO
writing top-level names to foo.egg-info\top_level.txt
writing dependency_links to foo.egg-info\dependency_links.txt
writing manifest file 'foo.egg-info\SOURCES.txt'
reading manifest file 'foo.egg-info\SOURCES.txt'
writing manifest file 'foo.egg-info\SOURCES.txt'
installing library code to build\bdist.win32\egg
running install_lib
running build_ext
building 'libfoo' extension
creating build
creating build\temp.win32-2.7
creating build\temp.win32-2.7\Release
creating build\temp.win32-2.7\Release\libfoo
c:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\BIN\cl.exe /c /nologo /Ox
/MD /W3 /GS- /DNDEBUG -I./libfoo -IC:\Python27\include -IC:\Python27\PC /Tclibfo
o/foo.c /Fobuild\temp.win32-2.7\Release\libfoo/foo.obj
foo.c
creating build\lib.win32-2.7
c:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\BIN\link.exe /DLL /nologo
/INCREMENTAL:NO /LIBPATH:C:\Python27\libs /LIBPATH:C:\Python27\PCbuild /EXPORT:i
nitlibfoo build\temp.win32-2.7\Release\libfoo/foo.obj /OUT:build\lib.win32-2.7\l
ibfoo.pyd /IMPLIB:build\temp.win32-2.7\Release\libfoo\libfoo.lib /MANIFESTFILE:b
uild\temp.win32-2.7\Release\libfoo\libfoo.pyd.manifest
LINK : error LNK2001: unresolved external symbol initlibfoo
build\temp.win32-2.7\Release\libfoo\libfoo.lib : fatal error LNK1120: 1 unresolv
ed externals
error: command 'c:\\Program Files (x86)\\Microsoft Visual Studio 9.0\\VC\\BIN\\l
ink.exe' failed with exit status 1120

似乎 distutils 包(在本例中为 setuputils)将始终从共享扩展中导出一个符号,即“init + extension_name”[Link] .

它在 Windows 链接器的“EXPORT”选项中指定 [Link]但找不到符号。

帮忙吗?

编辑:C 代码不使用 Python C API,即“#include”。这是因为该项目的目标是采用现有的 C 库并通过 Python 扩展封装在 Python 包装器中。该软件包适用于 Unix/Linux。

最佳答案

经过大量尝试,我终于明白了这个问题。

解决方案:在 Windows 中,您必须为您的扩展定义一个初始化函数,因为 setuptools 将构建一个 .pyd 文件,而不是一个 DLL

要在 Python 2 中解决这个问题,您可以在源代码中定义 initlibfoo() 方法。

#include <Python.h>

PyMODINIT_FUNC initlibfoo(void) {
// do stuff...
}

要在 Python 3 中解决此问题,您可以在源代码中定义 PyInit_libfoo() 方法。

#include <Python.h>

PyMODINIT_FUNC PyInit_libfoo(void) {
// do stuff...
}

所以现在,foo.c 看起来像:

#include <stdio.h>
#include <Python.h>

void foo() {
printf("Hello World!");
}

PyMODINIT_FUNC initlibfoo(void) // Python 2.7
//PyMODINIT_FUNC PyInit_libfoo(void) // Python 3.5
{
// do stuff...
}

解释

为 Windows 编译 Python 扩展时,Extension类会告诉 linker to export a function供其他程序调用。可以在终端输出中看到:

c:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\BIN\link.exe /DLL /nologo
/INCREMENTAL:NO /LIBPATH:C:\Python27\libs /LIBPATH:C:\Python27\PCbuild /EXPORT:i
nitlibfoo build\temp.win32-2.7\Release\libfoo/foo.obj /OUT:build\lib.win32-2.7\l
ibfoo.pyd /IMPLIB:build\temp.win32-2.7\Release\libfoo\libfoo.lib /MANIFESTFILE:b
uild\temp.win32-2.7\Release\libfoo\libfoo.pyd.manifest

(强调/EXPORT:initlibfoo)

现在这是 C/C++ 扩展的必需函数,以便它们可以作为模块导入。换句话说,当您 import libfoo 时,Python 将在 .pyd 上调用函数 initlibfoo 作为模块初始化的一部分。此处遇到的错误是由于链接器被告知导出函数 initlibfoo 但是它无法在 C 目标文件中找到该符号,因为它从未在源代码中定义!

当然,应该可以拒绝导出符号的选项吧?显然不是。回顾扩展类文档,有一个参数 export_symbols。我尝试将 None 传递给它,但仍在使用链接器选项。似乎没有办法绕过这个链接器选项。

不推荐:如果出于某种原因,需要 Python.h 困扰您,那么有一种解决方法。您仍然需要定义上面的“init”方法,但您可以这样做:

void initlibfoo() {} //Python 2.7
void PyInit_libfoo() {} //Python 3.5

但是现在,您不能通过import libfoo 使用该库。您可以使用 ctypes 模块并使用 ctypes.PyDLL('/path/to/pyd') 加载它。本质上,您使用 Python 为您构建了一个 DLL,在这种情况下,它确实构建了一个称为 .pyd 文件的特殊 DLL。然后要使用它,您必须通过 ctypes 模块加载它。

关于python - 在 Windows 中构建 Python C 扩展时导出符号时出错,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34689210/

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