我正在为GPIO驱动程序提供的功能编写Python extension。我在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端。
答案 0 :(得分:3)
您不需要在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
,以便在收到任何信号时(例如SIGINT
从终端按Ctrl + C),系统调用中断,控制返回到Python。
因此。您的实现可以只调用C wait_int
函数。如果它支持被信号中断,那么这将允许用户通过按Ctrl + C来中断它,但确保做出适当的反应,以便抛出异常(我不确定它是如何工作的,但是看起来从顶级函数(在此示例中为NULL
)返回time_sleep
将会起到作用)。
同样,为了获得更好的多线程性能,请使用一对Py_BEGIN_ALLOW_THREADS
/ Py_END_ALLOW_THREADS
宏来围绕等待调用,但这不是必需的,特别是如果您根本不使用多线程。