首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Python扩展打包DLL和pyd

Python扩展打包DLL和pyd
EN

Stack Overflow用户
提问于 2020-12-17 03:52:30
回答 1查看 787关注 0票数 1

我的项目将静态库(称为static.lib)公开给CPython (3.8)解释器。它由一个静态库组成,该库依赖于DLL FTDI驱动程序。在阅读这条线之后,提供第三方DLL的最佳解决方案似乎是将它们与package捆绑在一起,以确保DLL与.pyd二进制文件位于同一个目录中。

我遇到的问题是,在为我的包运行pip install .之后,所需的DLL (称为required.dll)放置在site-packages/package/required.dll中,而实际的C扩展库(称为package.pyd)放置在site-packages/package.pyd中。

因为当我尝试使用Python中的库时,它不在同一个目录中,所以

代码语言:javascript
复制
ImportError: DLL load failed while importing package: The specified module could not be found.

下面是我的setup.py

代码语言:javascript
复制
setuptools.setup(
        name="package",
        version="1.0.0",
        packages=setuptools.find_packages(where="src"),
        package_dir={"": "src"},
        py_modules=[splitext(basename(path))[0] for path in glob("src/*.py")],
        use_scm_version=True,
        package_data={
            "package": [
                "_clibs/libs/required.dll",
            ],
        },
        ext_modules=[
            setuptools.Extension(
                "package",
                include_dirs=["src/package/_clibs/inc"],
                sources=[
                    "src/package/_clibs/src/api.cpp",
                    "src/package/_clibs/src/utils.cpp",
                ],
                library_dirs=[
                    "src/package/_clibs/libs",
                ],
                libraries=["static", "User32"],
                language="c++"
            ),
        ],
    )

该项目的目录布局如下:

代码语言:javascript
复制
/
setup.py
.tox
src/
...package/
......wrapper.py
......__init__.py
......_clibs/
.........inc/
.........src/
............api.cpp
............utils.cpp
.........libs/
............required.dll
............static.lib

我还使用tox进行虚拟环境管理。

建议的答案这里这里概述了一个非常相似的setup.py和包含DLL通过package_data选项的相同方法。答案似乎表明DLL和.pyd放在相同的水平上,这对我来说是不可能的。我不知道我错过的是什么,得到了同样的行为。

代码语言:javascript
复制
python 3.8.6
setuptools 51.0.0
pip 20.3.1

DLL被放置在与.pyd二进制文件不同的目录中,从而使其在Windows加载程序中不可见

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-01-06 05:38:53

经过一番挖掘,我找到了一种适合我的方法。这个帖子揭示了在Windows上加载DLL的问题,以及最近(Python3.8)在这个问题上的发展。

我所使用的解决方案是从numpy借来的。为了正确地将DLL与C扩展捆绑在一起:

  1. 在包中创建包含扩展名将使用的所有必需DLL的目录。
  2. 修改构建过程,使其包括此目录以及sdist和轮询发行版。
  3. 一旦用户导入您的包,您首先要做的就是动态修改路径,以便搜索DLL的位置(两个不同的方法取决于您在3.8或更低版本上)

粗略地说,将package_data添加到您的setup.py应该可以做到这一点(除去清单文件附带的恶作剧和使用package_data,请阅读更多的这里)

代码语言:javascript
复制
 package_data={"your package name": ["path_to_DLLs/*"]},

要实现#3,作为包的__init__.py中的一个选项,添加以下内容(从numpy __config__.py逐行获取99%,由非常复杂的构建系统自动生成)。

代码语言:javascript
复制
import os
import sys

PATH_TO_DLL = "YOUR DLL DIRECTORY IN YOUR PACKAGE"
extra_dll_dir = os.path.join(os.path.dirname(__file__), PATH_TO_DLL)

if sys.version_info >= (3, 8):
    os.add_dll_directory(extra_dll_dir)
else:
    # legacy DLL loading mechanism through PATH env variable manipulations
    os.environ.setdefault("PATH", "")
    os.environ["PATH"] += os.pathsep + extra_dll_dir

任何反馈都是非常感谢的。链接到此票证的线程讨论了对C扩展板的更好文档的需求,我没有找到任何文档。到目前为止,C扩展+ Windows + setuptools提供了令人难以置信的令人沮丧的体验。

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

https://stackoverflow.com/questions/65334494

复制
相关文章

相似问题

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