是否可以在从 C 调用的 ctypes 回调中引发 Python 异常?
Is it possible to raise a Python exception inside a ctypes callback that is called from C?
我有一个使用 ctypes
封装的共享库。该库公开了可用于修改其错误处理行为的函数指针。我不想简单地打印警告或使用 exit(1)
终止进程,而是想引发一个 Python 异常,它可以在 Python 端被捕获和处理。
这是我正在尝试做的事情的草图:
import ctypes
mylib = ctypes.cdll.LoadLibrary('mylib.so')
error_handler_p = ctypes.c_void_p.in_dll(mylib, 'error_handler')
@ctypes.CFUNCTYPE(None, ctypes.c_char_p)
def custom_error_handler(message):
raise RuntimeError(message)
error_handler_p.value = ctypes.cast(custom_error_handler, ctypes.c_void_p).value
try:
mylib.do_something_bad()
except RuntimeError:
# maybe handle the exception here
目前似乎在回调中引发了异常,因为我在 STDERR 中看到了带有预期错误消息的回溯。但是,此异常似乎不会传播到调用 Python 进程,因为从未捕获到异常并且调用进程正常终止。
您必须使用 ctypes.PyDLL()
class (via the ctypes.pydll
loader) to access your library, and your C code would have to use the Python C API。
您通过调用 one of the PyErr_*
functions,然后返回 -1
来标记函数中的错误,从而 'raise' C 代码中的异常。然后 PyDLL()
class 将检查是否设置了异常。
您不能使用任何其他加载程序。请注意,PyDLL()
加载程序也不会释放 GIL;那将是您的扩展程序的责任(使用 macros supplied by the Python API headers)。
请注意,由于您 已经 必须使用 Python API 只是为了引发异常,您不妨公开您的 C 代码作为一个适当的Python 分机。
我有一个使用 ctypes
封装的共享库。该库公开了可用于修改其错误处理行为的函数指针。我不想简单地打印警告或使用 exit(1)
终止进程,而是想引发一个 Python 异常,它可以在 Python 端被捕获和处理。
这是我正在尝试做的事情的草图:
import ctypes
mylib = ctypes.cdll.LoadLibrary('mylib.so')
error_handler_p = ctypes.c_void_p.in_dll(mylib, 'error_handler')
@ctypes.CFUNCTYPE(None, ctypes.c_char_p)
def custom_error_handler(message):
raise RuntimeError(message)
error_handler_p.value = ctypes.cast(custom_error_handler, ctypes.c_void_p).value
try:
mylib.do_something_bad()
except RuntimeError:
# maybe handle the exception here
目前似乎在回调中引发了异常,因为我在 STDERR 中看到了带有预期错误消息的回溯。但是,此异常似乎不会传播到调用 Python 进程,因为从未捕获到异常并且调用进程正常终止。
您必须使用 ctypes.PyDLL()
class (via the ctypes.pydll
loader) to access your library, and your C code would have to use the Python C API。
您通过调用 one of the PyErr_*
functions,然后返回 -1
来标记函数中的错误,从而 'raise' C 代码中的异常。然后 PyDLL()
class 将检查是否设置了异常。
您不能使用任何其他加载程序。请注意,PyDLL()
加载程序也不会释放 GIL;那将是您的扩展程序的责任(使用 macros supplied by the Python API headers)。
请注意,由于您 已经 必须使用 Python API 只是为了引发异常,您不妨公开您的 C 代码作为一个适当的Python 分机。