【问题标题】:Receiving data in python callback function from dll从dll接收python回调函数中的数据
【发布时间】:2021-02-19 20:26:44
【问题描述】:

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

专有共享库

基本上,该 dll 包含一个函数,我必须调用该函数才能开始测量,并接收一个回调函数,该回调函数将在光谱仪完成测量时调用。函数如下:

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

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

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参数在这种情况下是个问题。

【问题讨论】:

    标签: python events dll callback scope


    【解决方案1】:

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

    # 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 的值的引用,因此当它被调用时,它可以对其进行操作,就好像它作为参数传递给功能。这样就可以得到传入的效果,回调调用者不必担心。

    【讨论】:

    • 我尝试使用函数闭包,但奇怪的是我无法访问全局范围变量,例如 numpy_array。无论如何,我实际上想得更多,实际上我需要其他参数,并且闭包函数最终会变得太复杂,所以我切换到了类方法。
    • 但是我在问题中首先提到的解决方案并没有完全起作用,因为self 不适用于我的装饰器。最终我在这里找到了解决方案:link .
    • 您应该发布您的特定解决方案作为答案,因为它可能是您问题的正确答案,而我的并不能解决您遇到的问题
    【解决方案2】:

    我终于设法解决了我的问题,该解决方案包含一个新类和一个闭包函数来处理self 描述的here 参数。除此之外,新创建的方法的垃圾回收会出现另一个问题。

    我的最终解决方案是:

    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)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-06-23
      • 2020-06-04
      • 1970-01-01
      相关资源
      最近更新 更多