我使用cytpes
打包C api。其中一个api函数允许您注册回调。我使用CFUNCTYPE
来指定函数的类型,并从我的python库的用户提供的python函数中创建CFUNCTYPE
的实例,然后将其传递给C函数(使用ctypes
api调用)。
我知道ctypes
次调用会释放GIL
。我想知道当C库函数调用我的python回调函数时会发生什么。 ctypes
是否重新获取GIL
?
注意:确保只要从C代码中使用
CFUNCTYPE()
个对象,就会保留对它们的引用。ctypes
没有,如果你不这样做,它们可能会被垃圾收集,在回调时会崩溃你的程序。 另请注意,如果在Python控件之外创建的线程中调用回调函数(例如,通过调用回调的外部代码),ctypes
会在每次调用时创建一个新的虚拟Python线程。对于大多数用途,此行为是正确的,但这意味着与threading.local
一起存储的值将无法在不同的回调中存活,即使这些调用是从同一个C线程进行的。
它没有对GIL
说些什么。这是否意味着它全部都是为我处理的?
答案 0 :(得分:4)
回调的_objects
属性中引用的CThunkObject
具有C库调用的pcl_exec
函数指针。此代码使用对thunk的引用调用closure_fcn
,加上调用args
和指向存储结果的内存的指针。闭包函数依次调用_CallPythonObject
,将thunk的restype
,setfunc
,callable
,converters
和flags
作为参数。 _CallPythonObject
做的第一件事是调用PyGILState_Ensure
来获取GIL。这是有效的,即使这是Python第一次看到当前的线程。
换句话说,这一切都是为你处理的。只需保留对回调的引用,以保持引用的thunk。