繁体   English   中英

Python C API:创建一定数量的PyObject后出现WindowsError

[英]Python C API: WindowsError after creating some number of PyObjects

我在获取Python C API时出现问题一直没有给我错误。

背景:一段时间以来,我一直在使用ctypes运行本机代码(C ++),但是直到现在我还从未真正使用Python C API做任何特定的事情。 我主要只是从Python传递结构,然后从C ++填充它们。 我使用结构的方式变得很麻烦,因此我决定尝试直接在C ++中创建Python对象,然后将它们传递回我的Python脚本。

代码:我有一个仅具有一个功能的DLL( Foo.dll ):

#define N 223
__declspec(dllexport) void Bar(void)
{
    std::cout << "Bar" << std::endl;

    for (int i = 0; i < N; ++i)
    {
        auto list = PyList_New(0);
        std::cout << "Created: " << i << std::endl;
        //Py_DECREF(list);
    }
}

然后,我正在运行Python脚本:

import ctypes as C
dll = r"C:\path\to\dll\Foo.dll"
Foo = C.CDLL(dll)
# lists = [[] for _ in range(0)]
Foo.Bar()
print "Done."

发生的情况:如果我在上述DLL中将N定义为222或以下,则代码可以正常工作(内存泄漏除外,但这不是问题)。

如果我取消注释//Py_DECREF(list)行,则代码可以正常工作。

但是,使用上面的代码,我得到了:

Bar
Created: 0
Created: 1
Created: 2
...(omitted for your sake)
Created: 219
Created: 220
Created: 221
Traceback (most recent call last):
  File "C:\path_to_script\script.py", line 9, in <module>
    Foo.Bar()
WindowsError: exception: access violation reading 0x00000028

实际上,使用字典,列表,元组等也可以得到相同的结果。 如果创建一个列表,然后将空的子列表附加到该列表,则会得到相同的结果。

奇怪的是,我在实际的Python脚本中创建的每个列表都会减少DLL在出现此Windows错误之前可以创建的列表数量。

仍然很奇怪,如果我在python脚本中制作了超过222个列表,则DLL将不会再出现此错误,除非它创建了720个以上的列表。

**其他详情: **

  • Windows 10
  • 使用Anaconda2 32位Python 2.7发行版
  • (使用该发行版中的Python.hpython27.lib
  • python.exe --version: 2.7.13 :: Anaconda custom (32-bit)
  • 使用Visual Studio 2017创建DLL

只要我不从我的C ++代码创建许多PyObject ,一切似乎就可以正常工作。 我可以在Python代码之间PyObject传递PyObject ,并且它可以正常工作..直到从C ++代码中创建了“太多”的对象。

到底是怎么回事?

从CDLL的文档中

在调用这些库导出的任何函数之前,先释放Python全局解释器锁,然后再重新获取。

这使得使用Python C API代码不安全 正如您所发现的,它到底如何失败是无法预测的。 我猜想这与分配是否触发垃圾收集器运行有关,但我认为花费太多时间来找出确切原因是不值得的。

至少有两种解决方案可供选择:

  1. 使用ctypes.PyDLL (文档注释与CDLL只是它不会释放GIL)
  2. 在您的C ++代码中重新获取GIL-一种简单的方法是:

     auto state = PyGILState_Ensure(); // C++ code requiring GIL - probably your entire loop PyGILState_Release(state); 

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM