【问题标题】:Pybind11 function call blocking main threadPybind11函数调用阻塞主线程
【发布时间】:2019-08-06 20:29:06
【问题描述】:

我正在使用 pybind11 将 this game code(用 c++ 编写)暴露给 python。

我要做的第一件事是,基本上通过在 c++ 部分中公开一个 start 函数来启动游戏。到目前为止看起来像这样(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 c++ python-multithreading gil pybind11


    【解决方案1】:

    这是因为 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;
    }
    

    【讨论】:

    • 完美运行。谢谢!
    • @MatheusZickuhr 总是在 stackoverflow 中使用 upvotes 说“谢谢” ;-)
    猜你喜欢
    • 1970-01-01
    • 2021-12-12
    • 2018-06-26
    • 2022-06-10
    • 1970-01-01
    • 2018-02-16
    • 1970-01-01
    • 2012-11-09
    • 2015-12-29
    相关资源
    最近更新 更多