python cffi在callb之后崩溃

2024-10-02 22:31:29 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个专有的dll接口与usb设备,ctypes接口工作正常,但cffi一是崩溃后调用回调。 如果函数SwitchOn(6)找到一个设备,它应该返回指向一个结构的指针;如果没有找到设备,它应该返回NULL;如果找不到设备,则返回错误回调,errno=10。在

我正在使用python27,py33的行为相同(需要删除“import thread”才能运行)

我用对了吗?如何调试它?在

尝试根据我的需要改编doc的例子。它仍然崩溃。我做得对吗?在

>>> cffi.__version__
'0.7.2'

ctypes示例输出:

^{pr2}$

cffi示例输出:

4504
(4504, 10L, 1L)

还有撞车

cffi公司_碰撞.py在

import thread
def error(errno, critical):
    print(thread.get_ident(), errno, critical)

from cffi import FFI
ffi = FFI()
ffi.cdef('''
void* SwitchOn(int FPort);
typedef void(*type_func_user_error)(unsigned int, unsigned int);
void SetErrorFunction(type_func_user_error);
''')
eeg_dll = ffi.dlopen("EEG4DLL.dll")
err_cb = ffi.callback('type_func_user_error', error)

eeg_dll.SetErrorFunction(err_cb)
print(thread.get_ident())
x = eeg_dll.SwitchOn(6)
print(x)

ctypes_编号_碰撞.py在

import thread

def error(errno, critical):
    print(thread.get_ident(), errno, critical)

import ctypes
from ctypes import c_uint, WINFUNCTYPE

eeg_dll = ctypes.windll.EEG4DLL
func_user_error = WINFUNCTYPE(None, c_uint, c_uint)

SetErrorFunction = eeg_dll.SetErrorFunction
SetErrorFunction.argtypes = [func_user_error]
SetErrorFunction.restype = None

err_cb = func_user_error(error)

eeg_dll.SetErrorFunction(err_cb)
print(thread.get_ident())
x = eeg_dll.SwitchOn(6)
print(x)

cffi公司_间接.py在

def error(errno, critical):
    print(errno, critical)

from cffi import FFI
ffi2 = FFI()
ffi2.cdef('''
void (*python_callback)(unsigned int, unsigned int);
void *const c_callback;
''')
wr = ffi2.verify('''
    static void(*python_callback)(unsigned int x, unsigned int y);
    static void c_callback(unsigned int x, unsigned int y) {
        python_callback(x, y);
    }
''')
err_cb = ffi2.callback('void(unsigned int, unsigned int)', error)
wr.python_callback = err_cb

ffi = FFI()
ffi.cdef('''
void* SwitchOn(int FPort);
typedef void(*type_func_user_error)(unsigned int, unsigned int);
void SetErrorFunction(type_func_user_error);
''')
eeg_dll = ffi.dlopen("EEG4DLL.dll")
eeg_dll.SetErrorFunction(wr.c_callback)
x = eeg_dll.SwitchOn(6)
print(x)

Tags: importcallbackerrorcffithreadintfuncdll
1条回答
网友
1楼 · 发布于 2024-10-02 22:31:29

根据文件say

Windows: you can’t yet specify the calling convention of callbacks… Use an indirection…

而崩溃(在函数返回后立即发生)看起来就像是通过传递一个cdecl函数并将其作为一个stdcall函数调用得到的:调用方(大概是C库中的SwitchOn函数)希望被调用方(CFFI围绕error函数的包装)清理堆栈;被调用方希望调用者清理堆栈…因此没有人清理堆栈,因此当SwitchOn尝试返回时,它将返回到您的某个参数或局部变量或其他垃圾,而不是返回到其调用方。在

紧接着,文档展示了如何“使用间接寻址”,也就是说,它们意味着编写一个您ffi.verify的C包装。(他们展示了如何传递varargs回调,但想法是一样的。)

相关问题 更多 >