使用 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