用于休眠函数的 Python C 扩展

标签 python c

我正在写一个Python extension用于 GPIO 驱动程序提供的功能。我在 set_bit() 和clear_bit() 等简单函数上很容易取得了进展。但现在我需要实现 wait_int(),它会休眠,直到在输入引脚上感测到事件为止,并且我不确定在 c 和 python 之间编排此事件的正确方法。下面是在 c 中使用该函数的精简示例:

main(int argc, char *argv[])
{
    int c;

    //some setup like testing port availability, clearing interrupts, etc
    ...

    while(1)
    {
        printf("**\n");
        c = wait_int(1);//sleeps until an interrupt occurs on chip 1
        if(c > 0) {
            printf("Event sense occured on Chip 1 bit %d\n",c);
            ++event_count;
        }
        else
            break;
    }

    printf("Event count = %05d\r",event_count);
    printf("\nExiting Now\n");
}

我是否直接公开 wait_int,然后执行无限循环的 python 等效惯用法是什么?还需要进行一些去抖操作。我已经在 c 中完成了它,但也许它可以移动到 python 端。

最佳答案

你不需要在Python端做任何事情,你可以把它当作一个同步函数。在 C 端,您只需阻塞直到事件发生,可能允许中断。例如,看一下 implementation time.sleep的功能:

/* LICENSE: http://docs.python.org/license.html */

/* Implement floatsleep() for various platforms.
   When interrupted (or when another error occurs), return -1 and
   set an exception; else return 0. */

static int
floatsleep(double secs)
{
/* XXX Should test for MS_WINDOWS first! */
#if defined(HAVE_SELECT) && !defined(__BEOS__) && !defined(__EMX__)
    struct timeval t;
    double frac;
    frac = fmod(secs, 1.0);
    secs = floor(secs);
    t.tv_sec = (long)secs;
    t.tv_usec = (long)(frac*1000000.0);
    Py_BEGIN_ALLOW_THREADS
    if (select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &t) != 0) {
#ifdef EINTR
        if (errno != EINTR) {
#else
        if (1) {
#endif
            Py_BLOCK_THREADS
            PyErr_SetFromErrno(PyExc_IOError);
            return -1;
        }
    }
    Py_END_ALLOW_THREADS
#elif defined(__WATCOMC__) && !defined(__QNX__)
    ...

它所做的只是使用select函数在给定的时间内休眠。使用 select 以便如果收到任何信号(例如在终端按 Ctrl+C 产生的 SIGINT),系统调用将被中断,控制权将返回到 Python。

因此。您的实现只需调用 C wait_int 函数即可。如果它支持被信号中断,那就太好了,这将允许用户通过按 Ctrl+C 来中断它,但请确保做出适当的 react ,以便抛出异常(我不确定这是如何工作的,但是看起来从顶级函数返回NULL(本例中为time_sleep)就可以解决问题。

同样,为了获得更好的多线程性能,请使用一对 Py_BEGIN_ALLOW_THREADS/Py_END_ALLOW_THREADS 宏包围等待调用,但这不是必需的,特别是如果您不使用根本就是多线程。

关于用于休眠函数的 Python C 扩展,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12828503/

相关文章:

python - 如何将自定义装饰器添加到FastAPI路由?

python - 带有自定义类实例的operator.index

Python 单元测试继承设置重写

c - 在回调中 RaiseException(...) win32 seh 异常是否安全? (在 x86 和 x64 上)

c - 在 C 程序文件中运行 cmd 命令

c - 指针前/后增量

python - 使用 SQLAlchemy 查询数据库的方法,其中日期是一周中的特定一天?

python - 按特定值填充 Pandas Dataframe 缺失值

Python - 使用 ctypes 在 C 和 Python 之间传递指针

添加到队列时在 C 和 Malloc 中创建队列