Callback with StdCall on a Background Thread?

I am assisting another user in trying to access his microscope USB camera, and after first successes I am out of ideas:

The camera is a ToupTek ToupCam which comes with drivers and documentation – we are trying a macOS version where the API is a dylib. The camera sends its replies via background threads, and yes I know these are not officially supported but there are workarounds that currently do work.

There is a hotPlug method which triggers a callback method each time a camera is connected or disconnected:

typedef void (*PTOUPCAM_HOTPLUG)(void* pCallbackCtx); toupcam_ports(void) Toupcam_HotPlug(PTOUPCAM_HOTPLUG pHotPlugCallback, void* pCallbackCtx);

With an external method

Private Sub Toupcam_HotPlug(Callback as ptr, context as ptr)

and an instance method

Private Sub InsertHotPlug() If Mid <> 0 Then Dim id As UInteger = Me.ID Toupcam_HotPlug AddressOf HotPlugCallBack, ptr(id) InstanceDictionary.Value(Mid) = xojo.core.WeakRef.Create(Me) xojo.core.timer.CallLater 0, WeakAddressOf Raiseconnected End If End Sub

I can register the shared method

Private Shared Sub HotPlugCallBack(context as Ptr) #Pragma BackgroundTasks False #Pragma StackOverflowChecking False Dim instance As ToupCam.Camera = GetInstance(context) If instance <> Nil Then CallDelegateOnMainThreadMBS AddressOf instance.RaiseCamerasChanged End If End Sub

which uses

Private Shared Function GetInstance(context as ptr) as ToupCam.Camera #Pragma BackgroundTasks False #Pragma StackOverflowChecking False Dim uid As UInt32 = Integer(context) Dim w As Xojo.Core.WeakRef = InstanceDictionary.Lookup(uid, Nil) If w <> Nil And w.Value <> Nil Then return toupcam.Camera(w.Value) End If End Function

to retrieve the instance. I am using the user customisable ptr “context” to register the id of the camera which is an Unsigned in C terms.
The code above works nicely although using plugins is not advised when trying to cope with a background thread, but I hoped that this part of Christian’s plugins would be thread savvy (else it wouldn’t make much sense) and it very much looks like that.

Now for the problem: There is another callback that is called when a variety of events occur which must be registered too:

typedef void (__stdcall* PTOUPCAM_EVENT_CALLBACK)(unsigned nEvent, void* pCallbackCtx); toupcam_ports(HRESULT) Toupcam_StartPullModeWithCallback(HToupCam h, PTOUPCAM_EVENT_CALLBACK pEventCallback, void* pCallbackContext);

HResult is

#ifndef HRESULT #define HRESULT int #endif

Obviously, the differences are that the handle of the camera is passed to the StartPullMode… method (the UInt32/unsigned I mentioned above), and that the callback method has two input parameters: an unsigned/UInt32 for the event definition and the custom ptr like above. And this method uses the stdCall calling convention. So here is the code:

Private Function Toupcam_StartPullModeWithCallback(id as uint32, callback as Ptr, context as ptr) as Int32

Public Function StartPullMode() as HResult Dim id As UInteger = Me.ID Return hresult(Toupcam_StartPullModeWithCallback (Mid, AddressOf EventCallBack, ptr(id))) End Function

[code]Private Shared Sub EventCallBack(eventID as Uint32, context as Ptr)
#Pragma BackgroundTasks False
#Pragma StackOverflowChecking False
#Pragma X86CallingConvention StdCall

System.DebugLog “Event Callback start”

Dim instance As ToupCam.Camera = GetInstance(context)
If instance <> Nil Then
System.DebugLog “Instance <> Nil”
System.DebugLog "eventid: "+eventid.ToText

Select Case eventID
  CallDelegateOnMainThreadMBS addressof instance.RaiseexposureChanged
  CallDelegateOnMainThreadMBS AddressOf instance.RaiseTempTintModeChanged
  System.DebugLog "Chrome eventID"
  CallDelegateOnMainThreadMBS AddressOf instance.RaiseImageArrived
  CallDelegateOnMainThreadMBS AddressOf instance.RaiseStillimageArrived
  CallDelegateOnMainThreadMBS AddressOf instance.RaiseRBGGainChanged
  CallDelegateOnMainThreadMBS AddressOf instance.RaiseError
  CallDelegateOnMainThreadMBS AddressOf instance.RaiseDisconnected
  System.DebugLog "Unknown eventID"
End Select

System.DebugLog “Instance is Nil”
End If
End Sub[/code]

But calling StartPullMode always results in a segmentation error, the “Event Callback start” does not appear in the debug log.
Any ideas what I have wrong (except for trying to catch a background thread in Xojo at all)?

Sorry for the length of this entry, and thank you for reading it!

for such callback, you need a plugin or put it in your own DLL.
For Xojo it will eventually always crash.

Too bad! Thank you!
Such a DLL shouldn’t be too hard I guess, but I’ve never done so.
There isn’t by chance a MBSCallBackBlock I might have not found yet?

for that I would need to know the parameter, e.g. which to just pass on and which to copy.