python - PyThreadState_GET() 从 PyImport_GetModuleDict() 中返回 NULL

标签 python c++ c windows python-3.x

我正在使用 Python 3.6 在 Windows 上工作。我有以下用于测试 python 解释器的简单嵌入代码:

Py_SetProgramName(L"MyApp");

Py_SetPath(
    L"C:\\Users\\rutski\\Documents\\python\\PCBuild\\amd64\\python36.zip;"
    L"C:\\Users\\rutski\\Documents\\python\\DLLs;"
    L"C:\\Users\\rutski\\Documents\\python\\lib;"
    L"C:\\Users\\rutski\\Documents\\python\\PCBuild\\amd64;"
    L"C:\\Users\\rutski\\Documents\\python;"
    L"C:\\Users\\rutski\\Documents\\python\\lib\\site-packages");

Py_Initialize();

PyRun_SimpleString(
    "from time import time,ctime\n"
    "print('Today is', ctime(time()))\n");

此代码在尝试从 PyRun_SimpleString() 中访问地址 0x00000010 时崩溃。事件的顺序是这样的:

  1. PyRun_SimpleString() 执行 AddModule("__main__")

  2. AddModule 执行 PyImport_GetModuleDict()

  3. PyImport_GetModuleDict() 尝试执行 PyThreadState_GET()->interp

  4. PyThreadState_GET() 返回 NULL,因此 ->interp 部分崩溃。

奇怪的是,从我的应用程序中直接调用 PyImport_GetModuleDict() 工作得很好。更奇怪的是,如果我用 main() 中的嵌入代码构建一个 Windows 命令行应用程序,并从终端执行它,整个事情实际上执行得很好。只有在构建 Windows GUI 应用程序并调用 WinMain() 中的嵌入代码时才会发生崩溃。

这是我在 Windows 上使用 PCbuild\build.bat 从源代码构建的 Python 解释器,以便我可以跟踪崩溃。但是,我使用 PCbuild\build.bat 在 Windows 上从源代码构建的 python windows installer.er 提供的股票解释器发生了完全相同的崩溃,因此我可以跟踪崩溃。但是,python Windows 安装程序提供的标准解释器也发生了完全相同的崩溃。

相关帖子似乎在这里:Embedding Python, works in main() but not in WinMain()

尽管该线程尚未解决,而且无论如何它不会以完全相同的方式崩溃。也许这只是因为他们在 3.4 而我在 3.6。也许根本问题是一样的。

最佳答案

在黑暗中跌跌撞撞之后,我找到了答案。下表显示了我对我的 WinMain() 应用程序的不同构建配置与不同的 python 库进行配对的测试结果。术语“发布”和“调试”指的是 Visual Studio 中的配置类型。所有构建均在 x64 模式下完成。

Debug   | python36.lib   | Works
Debug   | python36_d.lib | Works
Debug   | python3_d.lib  | Works
Debug   | python3.lib    | !!! CRASHES !!!
Release | python36.lib   | Works
Release | python36_d.lib | Works
Release | python3_d.lib  | !!! CRASHES !!!
Release | python3.lib    | Works

因此,选择不匹配的 python 二进制文件似乎会导致崩溃,但仅限于 python3,而不是 python36。这让我首先想知道两者之间的区别是什么。我开始崩溃是因为我将我的调试版本与发布版本 python3.lib 链接起来,因为我认为这无关紧要。

我的问题现在已解决,但如果有人能详细说明为什么会发生,那么我一定会感兴趣。

关于python - PyThreadState_GET() 从 PyImport_GetModuleDict() 中返回 NULL,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45558808/

相关文章:

python - Python 中 sum() 的时间复杂度是多少?

python - 从 flask 中的 mysql 提取信息时出现问题

c++ - C++ 运行时系统如何知道对象何时超出范围

c++ - 什么是 boost::ptr_vector::pop_front() 返回类型?

c++ - 动态添加对象?

c - 在 Windows 上使用 Cmake/CLion 编译 lzma 库的一种简单方法?

python - 如何在 Scikit-Learn 的随机森林分类器中设置子样本大小?特别是对于不平衡数据

c++ - ZMQ异步,具体是如何工作的?

c - FFTW 结果为零

python - 改变列表的元素