从dll接收python回调函数中的数据

2024-10-01 19:29:15 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在用Python编写一个程序,与Avantes的分光计进行通信。有一些专有DLL可用,其代码我无法访问,但它们有一些不错的文档。我很难找到一个好方法来存储通过回调收到的数据

专有共享库

基本上,dll包含一个我必须调用才能开始测量的函数,它接收一个回调函数,每当光谱仪完成测量时,就会调用该回调函数。功能如下:

int AVS_MeasureCallback(AvsHandle a_hDevice,void (*__Done)(AvsHandle*, int*),short a_Nmsr)

第一个参数是识别光谱仪的句柄对象,第二个是实际的回调函数,第三个是要进行的测量量。 回调函数随后将接收另一种类型的句柄,用于标识spetrometer和测量后可用数据量的信息

Python库

我正在使用一个library为许多设备(包括我的分光计)提供Python包装

def measure_callback(self, num_measurements, callback=None):
    self.sdk.AVS_MeasureCallback(self._handle, callback, num_measurements)

他们还定义了以下装饰器:

MeasureCallback = FUNCTYPE(None, POINTER(c_int32), POINTER(c_int32))

其思想是,当最终调用回调函数时,将触发get_data()函数,该函数将从设备检索数据

推荐的示例是

@MeasureCallback
def callback_fcn(handle, info):
    print('The DLL handle is:', handle.contents.value)
    if info.contents.value == 0:  # equals 0 if everything is okay (see manual)
       print('  callback data:', ava.get_data())

ava.measure_callback(-1, callback_fcn)

我的问题

我必须将接收到的数据存储在我在主代码中其他地方创建的2D numpy数组中,但我不知道用回调函数中可用的新数据更新该数组的最佳方法是什么。 我想知道是否可以将这个numpy数组作为回调函数的参数传递,但即使在这种情况下,我也找不到一个好的方法来传递,因为预期回调函数将只有这两个参数


编辑1

我找到了一个可能的解决办法here,但我不确定这是最好的办法。我不希望创建一个新类只是为了在其中保存一个numpy数组


编辑2

实际上,我改变了我的想法,因为在我的回调中,我想对接收到的数据执行许多操作,并将结果保存在许多不同的变量中。因此,我回到了前面提到的类方法here,在这里我基本上有一个类,其中包含所有变量,这些变量将以某种方式在回调函数中使用,并且还将继承或拥有类ava的对象

但是,如this other question所示,self参数在这种情况下是一个问题


Tags: 数据方法函数代码selfnumpydata参数
2条回答

如果不想创建新类,可以使用函数闭包:

# Initialize it however you want
numpy_array = ... 

def callback_fcn(handle, info):
    # Do what you want with the value of the variable
    store_data(numpy_array, ...)

# After the callback is called, you can access the changes made to the object
print(get_data(numpy_array))

其工作原理是,当callback_fcn被定义时,它保留了对变量numpy_array值的引用,因此在调用它时,它可以对其进行操作,就像它作为参数传递给函数一样。因此,您可以将其传入,而回调调用方不必担心它

最后,我通过一个包含一个新类的解决方案和一个闭包函数来解决我的问题,该闭包函数用于处理here中描述的self参数。除此之外,新创建的方法的垃圾收集还会出现另一个问题

我的最终解决办法是:

class spectrometer():
        
        def measurement_callback(self,handle,info):
            if info.contents.value >= 0:  
                timestamp,spectrum = self.ava.get_data()
                self.spectral_data[self.spectrum_index,:] = np.ctypeslib.as_array(spectrum[0:pixel_amount])
                self.timestamps[self.spectrum_index] = timestamp
                self.spectrum_index += 1
        
        def __init__(self,ava):
            self.ava = ava
            self.measurement_callback = MeasureCallback(self.measurement_callback)
            
        def register_callback(self,scans,pattern_amount,pixel_amount):
            self.spectrum_index = 0
            self.timestamps = np.empty((pattern_amount),dtype=np.uint32)
            self.spectral_data = np.empty((pattern_amount,pixel_amount),dtype=np.float64)
            self.ava.measure_callback(scans, self.measurement_callback)

相关问题 更多 >

    热门问题