CFRunLoopRun 挂起python程序

问题描述

我有一个 HID 设备,我正在尝试为其编写驱动程序。我编写了一个小 C 程序来使用 IOKit 转储输入报告,该程序以调用 CFRunLoopRun() 结束以持续观察报告。

鉴于我不知道报告的每个字节是什么意思(并且因为我只知道如何在 Python 中绘图),我想编写一个 Python 程序,该程序采用报告流并随时间绘制每个字节。

我不知道这是否是一个糟糕的主意(它看起来像一个)但我决定在阅读器中创建一个 Python/C 接口,以便我可以通过 Python 回调来绘制传入的报告。

这是创建 CFRunLoop 的 creader.read 函数一个片段:

static void creader_read(PyObject *self,PyObject *args)
{
    PyObject *cb;

    if (!PyArg_ParseTuple(args,"O",&cb)) {
        printf("Could not parse python args");
        return;
    }

    g_py_callback = cb;

    ...

    IOHIDManagerRegisterDeviceMatchingCallback(hidMan,deviceFound,hidMan);

    IOHIDManagerScheduleWithRunLoop(hidMan,CFRunLoopGetCurrent(),kcfRunLoopDefaultMode);

    CFRunLoopRun();
}

然后在设备匹配回调中:

void deviceFound(void *context,IOReturn result,void *sender,IOHIDDeviceRef device)
{
    printf("Found device\n");

    ...

    IOHIDDeviceScheduleWithRunLoop(device,kcfRunLoopDefaultMode);
    
    memset(g_report,REPORT_LENGTH);
    
    IOHIDDeviceRegisterInputReportCallback(device,g_report,REPORT_LENGTH,readCallback,NULL);
}

最后在读取回调中:

void readCallback(void *context,IOHIDReportType type,uint32_t reportID,uint8_t *report,CFIndex reportLength)
{   
    if (g_py_callback)
    {   
        PyObject *args = Py_BuildValue("s#",report,reportLength);
        PyEval_CallObject(g_py_callback,args);
    }
}

如果然后从 Python 解释器或脚本,我运行

import creader

def dump_report(report):
    print(report)

creader.read(dump_report)

我知道“找到设备”被打印出来,然后没有更多的输出。如果我尝试使用 Ctrl+C 或 Ctrl+D 退出程序,则没有任何反应——我必须从另一个终端选项卡手动 kill 进程。

我尝试将 creader.read调用封装在 try/except KeyboardInterrupt 中,但没有任何作用。

关于为什么忽略信号的任何想法?或者有人知道从 Python C 扩展调用 CFRunLoopRun() 的最佳做法吗?

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)