Python/C++ 包装器在 Pybind11

问题描述

Python 版本:3.8.1 Spyder 版本:3.3.6 Qt 版本:5.12.9 包装器:使用 PyBind11 开发

我正在用 C++ 包装一个 dll 开发,它使用 Qt dlls 与 Python 一起使用。我使用编译器 MSVC 用 Visual Studio 2019 编写了包装器(因为我的 dll 是用 MSVC 编译的)。在 VS2019 中生成解决方案后,我获得了一个可以用 python 导入的 .pyd 文件

当我使用 python 在线命令时效果很好:

  1. 开始cmd.exe
  2. $python
  3. import MyLibName 我可以使用函数/类...

但是如果我尝试使用 Spyder,我会收到以下错误

ImportError: DLL load Failed while importing PyStack: The specified module Could not be found..

这里是我的问题:

有没有办法获得更多关于 ImportError 的信息,比如丢失的 dll 的名字之类的?

我不明白为什么这个问题只发生在 spyder 上。我尝试使用 IPython Qt 控制台并且它工作正常。 spyder 是否使用了嵌入式 python 版本之类的?

我不完全理解 dll 应该如何管理,我的意思是我应该提供像 libGLESV2.dll 这样的 dll 和 .pyd 还是只提供一个可以找到它的路径?

提前致谢。

解决方法

我的猜测

我想我知道 Qt/python 的哪个部分产生了这个问题,但我仍然不知道如何解决它。

我的 dll 使用需要执行事件循环的信号/插槽。如果事件循环已经在运行,dll 将尝试使用它,如果循环版本(例如:PyQt5==5.14.1)与我的不同(例如 Qt==5.15.1)导入将是不可能的。

请注意,反之亦然,如果我运行我的 dll,然后尝试使用 %gui qt 启动循环,该命令将引发错误。

如何重现问题:

  1. 编译可用的 Qt 项目 here
  2. 复制VS项目的PyMyStack/dependencies文件夹下的输出dll(可用here
  3. 编译 VS 项目。
  4. 打开一个 IPython 控制台(不使用 qt 有事件循环)
  5. 导入使用 VS 创建的模块(导入 PyMyStack)
  6. 运行魔法命令 %gui qt

最后一条命令应打印:ERROR:root:DLL load failed while importing QtSvg: The specified procedure could not be found.

如何隐藏/解决问题:

免责声明:这里提供的解决方案肯定不是最好的,如果您知道更好的解决方案,请分享☺

如果您只想在 Spyder 中导入您的库,您可以使用另一个事件循环。以下是更改此设置的步骤:

  1. 在 Spyder 菜单中,转到工具→首选项
  2. 选择“IPython 控制台”
  3. 转到“图形”选项卡并将后端组合框更改为 Qt 或自动以外的任何其他值

如果你想使用 Qt 事件循环,你必须更新它。您可以使用 pip 命令执行此操作,但请记住,Spyder 与某些版本不兼容。这是pip命令:

Pip install PyQt5==X.Y.Z

其中 X 和 Y 是用于编译 Qt 项目的相同版本。最后一位数字版本似乎并不重要。