【发布时间】:2021-12-22 03:54:44
【问题描述】:
我有一个 C 函数分配一个整数,在返回指针之前将指针传递给回调函数。
void change_state(int gpio, int level, uint32_t tick, void *ptr){
if (level == 1){
printf("Button was pressed!\n");
*((int*)ptr) += 1;
}
}
int * allocate_void_ptr_start_watchdog(int BUTTON){
void *current_state_ptr = malloc(sizeof(int)); /*Creates a ptr of size int*/
*((int*)current_state_ptr) = 0; /*Casts ptr to type int and set to 0*/
gpioSetAlertFuncEx(BUTTON, change_state, current_state_ptr); /*Function to watch for GPIO state change*/
return current_state_ptr;
}
然后将返回值传回给 Python:
allocate_ptr_start_watchdog = button_functions.allocate_void_ptr_start_watchdog
allocate_ptr_start_watchdog.restype = ctypes.POINTER(ctypes.c_int)
ptr = allocate_ptr_start_watchdog(BUTTON)
使用while True 循环按预期工作(按 GPIO 25 处的按钮 1 次将打开灯,第二次按将其关闭)
while True:
current_val = ptr.contents.value
if current_val == 0:
continue
elif current_val == 1:
button_functions.turn_on_lights(LED_1, LED_2)
else:
button_functions.clear_all(LED_1, LED_2)
ptr.contents.value = 0
但是,一旦我尝试使用多处理功能,该功能就会中断,因为按下按钮不再打开或关闭灯。但是,C 库中的 printf 仍然可以打印,所以我怀疑这是库的问题。
def button_start(ptr):
while True:
current_val = ptr.contents.value
if current_val == 0:
continue
elif current_val == 1:
button_functions.turn_on_lights(LED_1, LED_2)
else:
button_functions.clear_all(LED_1, LED_2)
ptr.contents.value = 0
multiprocessing.Process(target=button_start, args=(ptr,)).start()
这是在内核 5.10.63-v7l+ 的 Raspbian Buster 上运行的。我在这里错过/看不到什么?
【问题讨论】:
-
介意告诉我们您在什么操作系统上运行它吗?
multiprocessing在 Linux 系统上使用不同的生成机制(fork而不是spawn),这可能会影响代码的加载方式。 -
@SilvioMayolo 目前在 Linux 上运行代码,更具体地说是 Raspbian buster,内核是 5.10.63。实际上这是问题所在,我的代码中有另一部分也调用多处理,它工作正常,但那部分是 python while 循环。
-
如果将所有 c 交互代码移动到多处理fn 会发生什么?即在多处理 fn 中定义 ptr,而不是传递它。还为你的 fn 添加一些调试:当它得到值时打印,当它试图打开或关闭灯时,这样你就可以看到到底是什么失败了。
-
顺便说一句,通常可以从 python 或通过
/sys/class/gpio中的虚拟文件获取 gpio 访问权限。这是一种解决方法,您正在做的事情也应该是可能的,但它可能值得尝试。 (完全避免使用 c 代码)。 -
@2e0byo 我有一个限制,只能使用 C 来使用 GPIO。但是我意识到似乎正在发生的事情是因为子进程与父进程不共享相同的状态过程中,代码的 MP 版本的 ptr 没有被看门狗函数更新。