繁体   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