pleiszenburg / zugbruecke

Calling routines in Windows DLLs from Python scripts running under Linux, MacOS or BSD
https://zugbruecke.readthedocs.io/en/latest/
GNU Lesser General Public License v2.1
111 stars 11 forks source link

Trigger memory sync between server and client #47

Open Stuermer opened 5 years ago

Stuermer commented 5 years ago

Hi, first of all. This project is amazing! My use-case is calling win dlls for hardware where there is no linux library available (unfortunatly very common). In this case an ethernet camera.

Now my problem: I'm calling a DLL function that has a pointer argument and reads data from the camera. However, the function is non-blocking and doesn't change the data on return. I'm supposed to call a second function that 'waits' until the exposure time is done and the data has been written to buffer. But since there is no additional 'sync', the data doesn't get updated on the linux client.

In code:

`

def read_ccd(self, n_img=1, n_clear=1, timeout=1000):
    __read_ccd__ = self.lib.CLReadCCDArea
    __read_ccd__.argtypes = (ctypes.c_int, POINTER(ctypes.c_ushort*128*1024), ctypes.c_uint, ctypes.c_uint)

    N, M = 128, 1024
    A = [ [0 for _ in range(N)] for __ in range(M)]
    _A = (ctypes.c_ushort * 128 * 1024)(*(tuple(eq) for eq in A))
    rv = __read_ccd__(self.handle, ctypes.pointer(_A), n_img, n_clear)  # non-blocking !
    if rv != 0:
        logger.error("Could not read CCD")

    __wait_for_ccd__ = self.lib.CLWaitCompletion
    __wait_for_ccd__.argtypes = (ctypes.c_int, ctypes.c_int)
    rv = __wait_for_ccd__(self.handle, timeout)
    if rv != 0:
        logger.error("Waiting for camera failed or timeout occured.")
    # TRIGGER _A.sync() somehow ?!
    return np.array(_A)  # still 'old' data

` From what I understand from the documentation, the issue is that the memsync happens when the DLL function call __readccd_ returns. But that's not when the DLL actually changes the data. Is there a way to 'trigger' another sync on that memory address afterwards ?

Thanks!

s-m-e commented 5 years ago

You're absolutely welcome.

Long story short: What you're trying to do is currently not possible with zugbruecke, I am afraid.

In detail: zugbruecke is state-less, i.e. does not maintain a state between function calls. Once the call into __read_ccd__ is done, zugbruecke does not keep track of the pointer to _A anymore. This problem falls within a larger category of other problems that I am currently trying to solve, which is unfortunately anything but trivial. From a design perspective, you just provided me with a good idea: I could enable you to tag/mark ctypes.pointer(_A) as "state-full", so zugbruecke does not drop it after a function call. I would have to add an API to the ctypes.pointer-class, including a sync method.

As a "workaround" in the meantime: You can write a simple Python script using the actual ctypes module and run it with wine-python, which is also provided by zugbruecke. "All you have to do then" is to set up some inter-process-communication between your Linux-Python and wine-python (Windows-Python on top of Wine). zugbruecke offers a simple and robust RPC-layer for that.