@Christian_Schmitz
The MBS documentation for CallDelegateOnMainThreadMBS says
“Our plugin supports various combinations of up to 2 parameters of type string, variant, boolean, double, integer and object.”
Nil is a valid value for a Variant, but passing a Nil Variant parameter via CallDelegateOnMainThreadMBS throws a NilObjectException, so it doesn’t really fully support Variant.
I have this code which works when Details is Nil:
EventHandler(HandlerObj.Value).HandleNotification(EventType, Details) //EventHandler is an Interface, EventType is a String, and Details is a Variant
and I want to make it thread-safe using the MBS method. This, however, throws an NOE when Details is Nil:
CallDelegateOnMainThreadMBS AddressOf EventHandler(HandlerObj.Value).HandleNotification, EventType, Details
If you get a NilObjectException, please check the message.
Our plugin would state if the delegate object or function is nil.
The parameter should not cause such an error.
NOE message info never shows anything
The only thing that’s Nil is Details
The WeakRef HandlerObj contains a reference to App. App conforms to the Interface and has a method
HandleNotification(EventName As String, Details as Variant)
I tried it with the deprecated CallMethodOnMainThreadMBS and that doesn’t throw an NOE but it returns False, indicating failure.
Ah, you’re right - if I assign a non-nil value to Details it still throws an NOE. So it seems maybe something to do with the the delegate resulting from AddressOf.
If I do
CallDelegateOnMainThreadMBS AddressOf App.HandleNotification, EventType, Details
it runs without error, but the problem is that the HandleNotification method can be on any object that conforms to the interface, not just App - that’s the point of using an interface.
So this works
EventHandlerIJ(HandlerObj.Value).HandleNotification(EventType, Details)
because it calls the interface method directly, but with
CallDelegateOnMainThreadMBS AddressOf EventHandler(HandlerObj.Value).HandleNotification, EventType, Details
AddressOf doesn’t work with the interface method, and I don’t know why.
AI explanation:
“AddressOf resolves at compile time against the static type, and when you wrap the object in an interface cast, the runtime delegate comes back Nil because Xojo can’t bind through the interface vtable that way.”
So it seems I need some kind of “interface forwarding” scheme.
Sorry for casting (no pun intended) aspersions on the plugin, @Christian_Schmitz. I’d change the topic title if I could.
What if you do something like
theEventHandler = EventHandler(HandlerObj.value)
CallDelegateOnMainThreadMBS AddressOf EventHandler(HandlerObj.Value).HandleNotification, EventType, Details
That might cause it to resolve properly.
Claude sorted it for me. Instead of storing interface objects and directly calling methods on them, “Forwarder” objects are instantiated and stored for each target object. Each Forwarder has a WeakRef to the target and its own method with the required signature, which in turn calls the interface method on the target:
Public Sub HandleNotification(EventType As String, Details As Variant)
If Target <> Nil And Target.Value <> Nil Then
EventHandlerIJ(Target.Value).HandleNotification(EventType, Details)
End
End Sub
AddressOf can now be called on the HandleNotification method of the Forwarder object, so it works with the MBS method:
Dim fwd As NotificationForwarder = HandlersArray(HandlerIndex)
If fwd.Target.Value <> Nil Then
CallDelegateOnMainThreadMBS AddressOf fwd.HandleNotification, EventType, Details
End If
1 Like