0

I am a bit stuck right now. This is more of a "how to approach this problem the right way" kind of question since I dont even know what exactly to type into google.

I got a scientific camera from thorlabs which only provides a C DLL as API. I wrote a python class to wrap the API using CFFI, which went really well. The API supports registering a callback method which is called when a new camera frame is available. Using CFFI it is possible to register python methods as callbacks, which are called by the DLL.

My ultimate goal is now to display the frames in a PyQt-Application. So I thought I might use the frame callback to emit a signal, which is connected to a pyqt-socket to draw the next frame.

The problem is now that the callback must provide the appropriate interface to be called by the API, which makes sense of course. But to emit a PyQt-signal, I need to call emit() on an object which is derived from QObject.

How can I get my generic callback method to get a hold on such an Object?

Since I want to separate the camera handling class from the GUI part, I dont really want to make a global QObject in the camera-class or something like that just so that I have an element to call (I dont really want to have any application-specific object inside the camera-class for that matter since I want to make it as generic as possible, if that makes any sense)

To test things, I wrote a small callback-method which just prints out a small message when called and used the provided set_callback method. I also tried to display the frames with matplotlib but that did not really work too well since matplotlib doesnt like to be invoked by a different thread. I just dont know how to appropriately deal with the data I receive in the callback method.

These are the required callback-type and the function to set the callback

typedef void(*TL_CAMERA_FRAME_AVAILABLE_CALLBACK)(void* sender, unsigned short* image_buffer, int frame_count, unsigned char* metadata, int metadata_size_in_bytes, void* context);

typedef int(*TL_CAMERA_SET_FRAME_AVAILABLE_CALLBACK)(void* tl_camera_handle, TL_CAMERA_FRAME_AVAILABLE_CALLBACK handler, void* context);

In Python, I can then create a callback-method and assign it

from _Thorlabscam import lib, ffi

@ffi.def_extern()
def python_frame_callback(sender, buffer, framecount, metadata, metasize, context):
    print("Frame acquired!")
    # How can I process all the nice data I have at this point?

lib.tl_camera_set_frame_available_callback(camHandle, frame_callback, ffi.NULL)

I am really sorry for this badly worded question, but I dont know how to combine those two concepts to work together. I could poll the camera with some loop but I want to make it event-driven because I find it to be "cleaner" (and I just want to get it working for my personal satisfaction :) ) Thank you all

  • 1
    If I understood you correctly, what about a model-view-controller design pattern? Your model would be the current frame, the view would be your PyQt Window, and the controller would be the camera (in the sense that the camera is the thing that updates the model, not necessarily because the user has much control over the camera). The advantage of this would be that things are generic and loosely coupled, and you can always extend your program with new types of views (like displaying things with Matplotlib) or controllers as long as they implement a certain interface. – Paul M. Jun 26 '19 at 11:18
  • Thanks for the reply. My main concern tho is how to propagate the data from the callback function forward. As far as Im concerned my options are either calling another static method out of the callback function or manipulate global variables, which then have to be monitored by a different task in an endless loop, defeating the purpose of using callbacks in the first place. From my understanding it should be possible to "trigger" the drawing of a new frame (or a similar action) out of the callback function but i just dont know how :/ – user3183627 Jun 26 '19 at 14:02

0 Answers0