使用 ctypes 扭曲无限循环
Warping a infinite loop using ctypes
我有一些 dll 可以控制硬件来获取一些信息。他们的工作方式是无限循环,每隔几秒就会不断获取新数据。
是否可以扭曲这个无限循环函数,以便在 python 中并行调用它,同时完成其他工作(定期检查循环中的新数据)?或者在 python 中复制循环会更好(我需要它们在每次执行时保存 C 函数的所有当前状态)?
换句话说,我想调用这个函数并让它开始获取,他们每隔几秒就会在数据峰值(来自 python)处查看它。
下面是一个最小的例子
在 C:
#include <stdio.h>
void loop()
{
while( 1 )
{
GetNewData();
sleep(1);
}
}
在 python:
import multiprocessing as mp
from multiprocessing.pool import Pool
from ctypes import *
def worker():
lib = CDLL("test.dll")
lib.loop()
def call(func):
global p
a = p.apply_async(func)
a.get()
if __name__ == '__main__':
p = Pool(1)
call(worker)
DoSomethingElse() # Code never reaches this point.
听起来您需要一个带有回调函数的线程以及停止它的方法。这是一个粗略的例子:
test.c
#ifdef _WIN32
# define API __declspec(dllexport)
#else
# define API
#endif
typedef void (*CALLBACK)(int);
int g_running;
API void run(CALLBACK cb) {
g_running = 1;
int data = 0;
while(g_running)
cb(data++);
}
API void stop() {
g_running = 0;
}
test.py
import ctypes as ct
import threading
import time
# ctypes wrapper for a C function callback.
# returns None and takes an integer.
CALLBACK = ct.CFUNCTYPE(None,ct.c_int)
dll = ct.CDLL('./test')
dll.run.argtypes = CALLBACK,
dll.run.restype = None
dll.stop.argtypes = ()
dll.stop.restype = None
# decorate a Python function with the ctypes callback
# and it can be passed to a C function and called.
@CALLBACK
def callback(data):
print(data)
time.sleep(.1) # just to slow it down.
# start a thread with the run function.
t = threading.Thread(target=dll.run, args=(callback,))
t.start()
time.sleep(.2)
print('\tdoing')
time.sleep(.2)
print('\tsomething')
time.sleep(.2)
print('\telse')
time.sleep(.4)
# issue stop and wait for graceful exit of thread
dll.stop()
t.join()
输出:
0
1
doing
2
3
something
4
5
else
6
7
8
9
我有一些 dll 可以控制硬件来获取一些信息。他们的工作方式是无限循环,每隔几秒就会不断获取新数据。
是否可以扭曲这个无限循环函数,以便在 python 中并行调用它,同时完成其他工作(定期检查循环中的新数据)?或者在 python 中复制循环会更好(我需要它们在每次执行时保存 C 函数的所有当前状态)?
换句话说,我想调用这个函数并让它开始获取,他们每隔几秒就会在数据峰值(来自 python)处查看它。
下面是一个最小的例子
在 C:
#include <stdio.h>
void loop()
{
while( 1 )
{
GetNewData();
sleep(1);
}
}
在 python:
import multiprocessing as mp
from multiprocessing.pool import Pool
from ctypes import *
def worker():
lib = CDLL("test.dll")
lib.loop()
def call(func):
global p
a = p.apply_async(func)
a.get()
if __name__ == '__main__':
p = Pool(1)
call(worker)
DoSomethingElse() # Code never reaches this point.
听起来您需要一个带有回调函数的线程以及停止它的方法。这是一个粗略的例子:
test.c
#ifdef _WIN32
# define API __declspec(dllexport)
#else
# define API
#endif
typedef void (*CALLBACK)(int);
int g_running;
API void run(CALLBACK cb) {
g_running = 1;
int data = 0;
while(g_running)
cb(data++);
}
API void stop() {
g_running = 0;
}
test.py
import ctypes as ct
import threading
import time
# ctypes wrapper for a C function callback.
# returns None and takes an integer.
CALLBACK = ct.CFUNCTYPE(None,ct.c_int)
dll = ct.CDLL('./test')
dll.run.argtypes = CALLBACK,
dll.run.restype = None
dll.stop.argtypes = ()
dll.stop.restype = None
# decorate a Python function with the ctypes callback
# and it can be passed to a C function and called.
@CALLBACK
def callback(data):
print(data)
time.sleep(.1) # just to slow it down.
# start a thread with the run function.
t = threading.Thread(target=dll.run, args=(callback,))
t.start()
time.sleep(.2)
print('\tdoing')
time.sleep(.2)
print('\tsomething')
time.sleep(.2)
print('\telse')
time.sleep(.4)
# issue stop and wait for graceful exit of thread
dll.stop()
t.join()
输出:
0
1
doing
2
3
something
4
5
else
6
7
8
9