nidaqmx-python
nidaqmx-python copied to clipboard
Event Callbacks Contain Unusable Parameters
Original discussion on NI's forms.
DAQmx's event callback signatures include a Task ID and callbackData parameters even though there currently isn't a way to get a task object from a Task ID or be able to pass in user provided callbackData (register_every_n_samples_acquired_into_buffer_event passes None as the data.)
Having to specify these to parameters in the signature even though they are not usable is confusing the users.
These are 2 ideas on how to improve this.
- Provide a way to pass in user provided data and get a task object from a Task ID.
- Make the callback signature that users provide not have to specify those and wrap their callback in an internal one to the event register functions.
- Might also be able to pass reference to task object that referenced it by passing self from internal_callback wrapper.
Is there really no way to pass user variables in for callback_data? That would be unfortunate.
You can reference variables in the callback by creating an inner function (also called nested function) and Python allows you to reference variables from the enclosing function. You can see this being done in the every_n_samples_event.py example with the "callback" inner function referencing "samples" from the enclosed function.
Ahh I see, thank you very much!
Thanks, this helped me as well.
For anyone else reading this in the future, here the perma-link to the code version referenced above by @maxxboehme :
https://github.com/ni/nidaqmx-python/blob/caf1b1cede57b5413d96077ba3ee61e243d83547/nidaqmx_examples/every_n_samples_event.py#L21
FYI, here are two ways to pass user variables to the callback without using local functions (untested):
- Use functools.partial
def callback_with_extra_param(extra_param, task_handle, every_n_samples_event_type, number_of_samples, callback_data): ... callback = functools.partial(callback_with_extra_param, 123) task.register_every_n_samples_acquired_into_buffer_event(1000, callback)
- Write a class with a
__call__
methodclass CallbackWithExtraParam: def __init__(self, extra_param): self.extra_param = extra_param def __call__(self, task_handle, every_n_samples_event_type, number_of_samples, callback_data): ... callback = CallbackWithExtraParam(123) task.register_every_n_samples_acquired_into_buffer_event(1000, callback)
(Still, we should fix this.)