使用 ctypes 使用 Ctrl-C 中断 Python C 扩展
Interrupting a Python C-extension with Ctrl-C using ctypes
我正在为 C 扩展创建一个 Python 包装器,它是传感器的驱动程序。
我需要将带有 Python 的 Ctrl-C 中断信号传递给驱动程序,以便它结束当前采集阶段并且不会开始新的采集阶段。
我发现了这两个相关主题:
Allowing Ctrl-C to interrupt a python C-extension
Allowing Ctrl-C to interrupt a python C-extension
但是他们没有回答我的问题,因为我正在使用 Ctypes(见下文)。
有没有办法使用 Python 的线程或 ctypes 来中断 C 扩展。我想避免对 C 代码进行任何更改。
目标是停止无限循环功能
Python代码:
import signal
import ctypes
import os
import sys
if __name__ == "__main__" :
libname = os.path.abspath(os.path.join(os.path.dirname(__file__),"clib.so"))
LIBC = ctypes.CDLL(libname)
LIBC.main.argtypes = [ctypes.c_int, ctypes.POINTER(ctypes.c_char_p),]
args=(ctypes.c_char_p * (len(sys.argv)-1))(str.encode(sys.argv[1]))
LIBC.main(len(args),args)
signal.signal(signal.SIGINT, lambda s,f:os.kill(os.getpid(), signal.SIGTERM))
C代码:
#include <stdlib.h>
#include <stdio.h>
#incluse <string.h>
void endless_loop()
{
while(1){printf("Can't stop me ! \n");}
}
int main(int argc, char* argv[])
{
endless_loop();
return 0 ;
}
生成文件:
all: test
clean:
rm -f *.o *.so *.html
clib.so: clib.o
gcc -shared -o clib.so clib.c -fPIC
clib.o: clib.c
gcc -Wall -Werror clib.c -fPIC
test: clib.so
chmod 777 pyclib.py
python pyclib.py 2
谢天谢地,
LIBC.main(len(args),args)
signal.signal(signal.SIGINT, lambda s,f:os.kill(os.getpid(), signal.SIGTERM))
如果您希望在 LIBC.main
为 运行 时调用信号处理程序,则必须在调用 LIBC.main
之前安装它(通过 signal.signal
),而不是之后它 returns.
但是,正如您所注意到的:它仍然不起作用。这是因为 Python 信号处理程序不会在 C 扩展为 运行 时执行,并且由于 Python 主动安装 SIGINT 处理程序,默认情况下 Ctrl-C 不会在这种情况下无法工作。为了让它中断程序,恢复默认的信号行为:
signal.signal(signal.SIGINT, signal.SIG_DFL)
LIBC.main(len(args), args)
我正在为 C 扩展创建一个 Python 包装器,它是传感器的驱动程序。 我需要将带有 Python 的 Ctrl-C 中断信号传递给驱动程序,以便它结束当前采集阶段并且不会开始新的采集阶段。 我发现了这两个相关主题: Allowing Ctrl-C to interrupt a python C-extension Allowing Ctrl-C to interrupt a python C-extension 但是他们没有回答我的问题,因为我正在使用 Ctypes(见下文)。 有没有办法使用 Python 的线程或 ctypes 来中断 C 扩展。我想避免对 C 代码进行任何更改。 目标是停止无限循环功能
Python代码:
import signal
import ctypes
import os
import sys
if __name__ == "__main__" :
libname = os.path.abspath(os.path.join(os.path.dirname(__file__),"clib.so"))
LIBC = ctypes.CDLL(libname)
LIBC.main.argtypes = [ctypes.c_int, ctypes.POINTER(ctypes.c_char_p),]
args=(ctypes.c_char_p * (len(sys.argv)-1))(str.encode(sys.argv[1]))
LIBC.main(len(args),args)
signal.signal(signal.SIGINT, lambda s,f:os.kill(os.getpid(), signal.SIGTERM))
C代码:
#include <stdlib.h>
#include <stdio.h>
#incluse <string.h>
void endless_loop()
{
while(1){printf("Can't stop me ! \n");}
}
int main(int argc, char* argv[])
{
endless_loop();
return 0 ;
}
生成文件:
all: test
clean:
rm -f *.o *.so *.html
clib.so: clib.o
gcc -shared -o clib.so clib.c -fPIC
clib.o: clib.c
gcc -Wall -Werror clib.c -fPIC
test: clib.so
chmod 777 pyclib.py
python pyclib.py 2
谢天谢地,
LIBC.main(len(args),args) signal.signal(signal.SIGINT, lambda s,f:os.kill(os.getpid(), signal.SIGTERM))
如果您希望在 LIBC.main
为 运行 时调用信号处理程序,则必须在调用 LIBC.main
之前安装它(通过 signal.signal
),而不是之后它 returns.
但是,正如您所注意到的:它仍然不起作用。这是因为 Python 信号处理程序不会在 C 扩展为 运行 时执行,并且由于 Python 主动安装 SIGINT 处理程序,默认情况下 Ctrl-C 不会在这种情况下无法工作。为了让它中断程序,恢复默认的信号行为:
signal.signal(signal.SIGINT, signal.SIG_DFL)
LIBC.main(len(args), args)