簡體   English   中英

當dll具有嵌入式Python解釋器時,將函數從dll(用C ++編程)導入Python腳本

[英]Import functions from dll (programmed in C++) into Python script when the dll has an embedded Python interpreter

我用C ++編寫了一個使用嵌入式Python解釋器的庫(dll)。 當C ++程序使用該庫時,在嵌入式解釋器中執行Python腳本可以正常工作。

如果我從Python程序調用dll的功能,則會遇到麻煩。 當dll通常通過調用Py_Initialize()啟動嵌入式解釋器時,已經有一個正在運行的解釋器(我可以通過調用Py_IsInitialized()進行測試)。 當我嘗試使用此解釋器時,程序崩潰。

重現該行為的最小示例:

dll的代碼:

#include "stdafx.h"
#include <Python.h>

extern "C" __declspec(dllexport)
int testIsInitialized()
{
  return Py_IsInitialized();
}

extern "C" __declspec(dllexport)
void testRunSimpleString()
{
  PyRun_SimpleString("print('test')");
}

Python腳本:

import ctypes

dll=ctypes.windll.LoadLibrary('pytest.dll')

# test if Python interpreter is initialized
print(dll.testIsInitialized())

# test if we can run a simple Python script
dll.testRunSimpleString()

輸出:

1
Traceback (most recent call last):
  File "test_dll.py", line 9, in <module>
    dll.testRunSimpleString()
OSError: exception: access violation reading 0x0000000000000010 

我的主要問題是:如何從其他Python程序導入的c ++庫中執行Python代碼?

UPDATE

當我在testRunSImpleString()函數中獲取全局解釋器鎖(GIL)時,該示例將起作用。 我不明白為什么這是必要的。

ctypes庫具有幾個類來加載不同類型的DLL。 兩個相關的類是:

  • ctypes.CDLL (即C DLL)-用於加載使用標准C調用約定的DLL。 這包括定義extern "C" C ++ DLL。
  • ctypes.PyDLL與C DLL相似,但在函數調用期間未釋放Python GIL。 直接調用Python C API函數很有用。

加載使用Python C API的C ++ DLL(即Python.h )時,請使用ctypes.PyDLL

import ctypes

dll = ctypes.PyDLL('pytest.dll')

# then do whatever
dll.testRunSimpleString.argtypes = []
dll.testRunSimpleString.restype = None
dll.testRunSimpleString()

PyDLL要記住的一件事是,由於解釋器已經在運行,因此您無需從C ++ API調用Py_Initialize()Py_Finalize() / Py_FinalizeEx() 您可以先檢查(並存儲) Py_IsInitialized()來查看是否需要啟動/停止新的解釋器。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM