python - Pybind11 函数调用阻塞主线程

标签 python c++ python-multithreading gil pybind11

我正在使用 pybind11 公开 this game code (用 C++ 编写)到 Python。

我尝试做的第一件事是,通过在 C++ 部分公开一个启动函数来启动游戏。到目前为止看起来像这样(c++):

#define NOMINMAX

#include "GameWinMain.h"
#include "GameEngine.h"
#include <iostream>

#include "Contra.h"
#include <pybind11/pybind11.h>

namespace py = pybind11;

using namespace  std;

#define GAME_ENGINE (GameEngine::GetSingleton())

int start()
{
    // Enable run-time memory leak check for debug builds.
#if defined(DEBUG) | defined(_DEBUG)
    _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
#endif
    WinMain(GetModuleHandle(0), 0, 0, SW_SHOW);

    return 0;
}

int _tmain()
{
    start();
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
{
    if (GAME_ENGINE == NULL) return FALSE; // create the game engine and exit if it fails
    GAME_ENGINE->SetGame(new Contra()); // any class that implements AbstractGame
    cout << "jogo foi iniciado?";
    return GAME_ENGINE->Run(hInstance, iCmdShow); // run the game engine and return the result
}

PYBIND11_MODULE(contra, m)
{
    cout << "modulo importado! ";
    m.doc() = "contra game";
    m.def("start", &start, "starts the contra game");
}

在 python 端看起来像这样:

from threading import Thread
from Contra_remake import contra

Thread(target=contra.start, args=()).start()

print('print!')

问题是,打印行只在游戏关闭时执行,即使在另一个线程中开始游戏也是如此。

最佳答案

那是因为 Python 的 GIL(全局解释器锁)。您可以阅读更多相关信息 here .

如果您想解决这个问题,您应该在您的 C++ 代码中手动释放 GIL,如 this link 中所述。 .

简而言之,您可以像下面这样更改您的启动方法,以避免您的 Python 线程被阻塞:

#include <python.h>

class GilManager
{
public:
   GilManager()
   {
      mThreadState = PyEval_SaveThread();
   }

   ~GilManager()
   {
      if (mThreadState)
         PyEval_RestoreThread(mThreadState);
   }

   GilManager(const GilManager&) = delete;
   GilManager& operator=(const GilManager&) = delete;
private:
   PyThreadState* mThreadState;
};

int start()
{
   GilManager g;
    // Enable run-time memory leak check for debug builds.
#if defined(DEBUG) | defined(_DEBUG)
    _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
#endif
    WinMain(GetModuleHandle(0), 0, 0, SW_SHOW);

    return 0;
}

关于python - Pybind11 函数调用阻塞主线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57383574/

相关文章:

python - 使用 python 实现基于 Web 的桌面应用程序

C++按值传递结构数组

c++ - c++ 有一个好的通用选项类吗?

python - 我如何等待 ThreadPoolExecutor.map 完成

python - python 中的并行性无法正常工作

python-2.7 - 在python qt中带有线程的Qwebview

python - 如何在处理请求重试时覆盖 BACKOFF_MAX

python - 单击图像1次,获取位置并销毁OpenCv窗口

python - Python中频谱图的FFT

c++ - 在 C++ 中查看 UDP 消息