2013-07-24 130 views
4

为了将它放到上下文中,我正在为C DLL创建一个包装器 - 相当复杂的用例,但请坚持下去!Python Ctypes&Threading

在我的包装类的初始化过程中,我为我的C DLL的函数创建了别名,以便我的类可以稍后轻松访问它们。我做的另外一个任务是将一个回调函数传递给我的类中的一个函数到我的DLL中,该函数保存在一个静态变量中并在以后使用。

最后,我产生了另一个线程,它重复调用我的DLL中的一个函数,它在执行中的某些工作和不同点上需要使用在我的类的init阶段中分配的回调来调用Python程序。

当回调以这种方式被调用我收到以下:

WindowsError: exception: access violation reading 0x00000001 

我怀疑这是做穿线,因为当我在同一个线程测试回调,我赋予它的DLL可以成功地调用它,并且所有的参数都传递给Python。是否有一些保护措施是通过我的DLL中的变量强制执行的,我使用它来保持我的回调?

+4

保留对Python方面的回调的引用,例如将其分配给全局。 – jfs

+0

什么,仍然继续做我在做什么? –

+2

看看回调的'_objects'属性。它保留了一个['CThunkObject'](http://hg.python.org/cpython/file/ab05e7dd2788/Modules/_ctypes/ctypes.h#l96)的引用,该引用具有'pcl_exec' C函数,标志,转换器,restype和Python可调用。不要让垃圾收集,否则你会得到一个访问冲突(ctypes'方便'处理Windows SEH异常...希望你只是记录它,让这个过程死掉)。 – eryksun

回答

2

从Python文档上的ctypes:

的回调函数的重要注意事项:

请务必保持引用,只要它们是由C语言中使用CFUNCTYPE对象。 ctypes不会,如果你不这样做,它们可能会被垃圾收集,在回调时崩溃你的程序。

如果您看到“访问违规”或“分段错误”,并且您正在处理回调,那很可能是原因。正如J.F.塞巴斯蒂安所说,全局变量是一种选择,尽管我通常在我的课程中保留了对主动回调的引用列表。

当不涉及回调时,请仔细检查包装中的类型。声明一个错误的类型会变得很难看,而且很难弄清楚。