Swift closure isn't allowed to capture context

SG
Stefan Godoroja
Sat, Nov 12, 2016 8:31 PM

Hi guys,

Recently I was trying to use pjsip stack libraries in an iOS project which uses Swift language, but I have noticed
a thing which makes library hard to use. C function pointers are translated into Swift closures, a special type of closure. The problem is
that Swift doesn’t allow to capture context (self) in this type of closure. Looking into the source code of pjsip libs convinced me that
pjsip callbacks don’t have a parameter for referencing context. I’m not a C specialist but this seems to me at least not ok.

I’m addressing the developers who used library in Swift projects, how did you handle this situation ?

Best regards,
Stefan

Hi guys, Recently I was trying to use pjsip stack libraries in an iOS project which uses Swift language, but I have noticed a thing which makes library hard to use. C function pointers are translated into Swift closures, a special type of closure. The problem is that Swift doesn’t allow to capture context (self) in this type of closure. Looking into the source code of pjsip libs convinced me that pjsip callbacks don’t have a parameter for referencing context. I’m not a C specialist but this seems to me at least not ok. I’m addressing the developers who used library in Swift projects, how did you handle this situation ? Best regards, Stefan
CM
Colin Morelli
Sat, Nov 12, 2016 9:44 PM

Hey Stefan,

This might not be entirely helpful to you depending on your use case, but I
am using pjsip in a swift application. I actually ended up wrapping
everything PJSIP in Objective-C. Interfacing with C code is much easier
in Obj-C IMO (without the constant wrapping/unwrapping of
UnsafeMutablePointers). The Swift <-> Obj-C interop is much more refined
than Swift<->C.

That said, even in Objective-C you have to find a place to store context.
In my application, my custom objective-c wrapper around calls/accounts is
stored in the user data of the call with pjsua_call_set_user_data(callId, (
__bridge void *) self);

Callbacks end up looking like:

static void onCallState(pjsua_call_id callId, pjsip_event *event) {
void *data = pjsua_call_get_user_data(callId);
if (data == NULL) {
return;
}

@autoreleasepool {
SBSCall *call = (__bridge SBSCall *) data;
[call handleCallStateChange:event];
}
}

I hope that's helpful in some way.

Best,
Colin

On Sat, Nov 12, 2016 at 3:32 PM Stefan Godoroja mancunianetz@me.com wrote:

Hi guys,

Recently I was trying to use pjsip stack libraries in an iOS project which
uses Swift language, but I have noticed
a thing which makes library hard to use. C function pointers are
translated into Swift closures, a special type of closure. The problem is
that Swift doesn’t allow to capture context (self) in this type of
closure. Looking into the source code of pjsip libs convinced me that
pjsip callbacks don’t have a parameter for referencing context. I’m not a
C specialist but this seems to me at least not ok.

I’m addressing the developers who used library in Swift projects, how did
you handle this situation ?

Best regards,
Stefan


Visit our blog: http://blog.pjsip.org

pjsip mailing list
pjsip@lists.pjsip.org
http://lists.pjsip.org/mailman/listinfo/pjsip_lists.pjsip.org

Hey Stefan, This might not be entirely helpful to you depending on your use case, but I am using pjsip in a swift application. I actually ended up wrapping everything PJSIP in Objective-C. Interfacing with C code is *much* easier in Obj-C IMO (without the constant wrapping/unwrapping of UnsafeMutablePointers). The Swift <-> Obj-C interop is much more refined than Swift<->C. That said, even in Objective-C you have to find a place to store context. In my application, my custom objective-c wrapper around calls/accounts is stored in the user data of the call with pjsua_call_set_user_data(callId, ( __bridge void *) self); Callbacks end up looking like: static void onCallState(pjsua_call_id callId, pjsip_event *event) { void *data = pjsua_call_get_user_data(callId); if (data == NULL) { return; } @autoreleasepool { SBSCall *call = (__bridge SBSCall *) data; [call handleCallStateChange:event]; } } I hope that's helpful in some way. Best, Colin On Sat, Nov 12, 2016 at 3:32 PM Stefan Godoroja <mancunianetz@me.com> wrote: > Hi guys, > > Recently I was trying to use pjsip stack libraries in an iOS project which > uses Swift language, but I have noticed > a thing which makes library hard to use. C function pointers are > translated into Swift closures, a special type of closure. The problem is > that Swift doesn’t allow to capture context (self) in this type of > closure. Looking into the source code of pjsip libs convinced me that > pjsip callbacks don’t have a parameter for referencing context. I’m not a > C specialist but this seems to me at least not ok. > > I’m addressing the developers who used library in Swift projects, how did > you handle this situation ? > > > > Best regards, > Stefan > > > > > _______________________________________________ > Visit our blog: http://blog.pjsip.org > > pjsip mailing list > pjsip@lists.pjsip.org > http://lists.pjsip.org/mailman/listinfo/pjsip_lists.pjsip.org >
AR
Alin Radut
Mon, Nov 14, 2016 11:27 AM

Hi Stefan

An approach that worked for me when working with callbacks was to pass the
information received from the callback to a static method on a dispatcher
class that would handle the processing of the data. My idea was to get out
of the callback as fast as possible and do the heavy lifting in a real
Swift environment.

For example, for the call state callback:

uaConfig.memory.cb.on_call_state = { (callId, event) -> Void in
Dispatch.dispatch({ () -> Void in Dispatch.dispatchCallState(callId,
event: event) })
}

Where Dispatch.dispatch() just executes the closure that I pass to it on a
serial queue.

Dispatch.dispatchCallState() is a static function that collects all the
relevant information it receives and passes it down to a Call swift object.
You can use here a notification, a call registry, whatever is most
convenient.

Alin

On Sat, Nov 12, 2016 at 10:31 PM, Stefan Godoroja mancunianetz@me.com
wrote:

Hi guys,

Recently I was trying to use pjsip stack libraries in an iOS project which
uses Swift language, but I have noticed
a thing which makes library hard to use. C function pointers are
translated into Swift closures, a special type of closure. The problem is
that Swift doesn’t allow to capture context (self) in this type of
closure. Looking into the source code of pjsip libs convinced me that
pjsip callbacks don’t have a parameter for referencing context. I’m not a
C specialist but this seems to me at least not ok.

I’m addressing the developers who used library in Swift projects, how did
you handle this situation ?

Best regards,
Stefan


Visit our blog: http://blog.pjsip.org

pjsip mailing list
pjsip@lists.pjsip.org
http://lists.pjsip.org/mailman/listinfo/pjsip_lists.pjsip.org

Hi Stefan An approach that worked for me when working with callbacks was to pass the information received from the callback to a static method on a dispatcher class that would handle the processing of the data. My idea was to get out of the callback as fast as possible and do the heavy lifting in a real Swift environment. For example, for the call state callback: uaConfig.memory.cb.on_call_state = { (callId, event) -> Void in Dispatch.dispatch({ () -> Void in Dispatch.dispatchCallState(callId, event: event) }) } Where Dispatch.dispatch() just executes the closure that I pass to it on a serial queue. Dispatch.dispatchCallState() is a static function that collects all the relevant information it receives and passes it down to a Call swift object. You can use here a notification, a call registry, whatever is most convenient. Alin On Sat, Nov 12, 2016 at 10:31 PM, Stefan Godoroja <mancunianetz@me.com> wrote: > Hi guys, > > Recently I was trying to use pjsip stack libraries in an iOS project which > uses Swift language, but I have noticed > a thing which makes library hard to use. C function pointers are > translated into Swift closures, a special type of closure. The problem is > that Swift doesn’t allow to capture context (self) in this type of > closure. Looking into the source code of pjsip libs convinced me that > pjsip callbacks don’t have a parameter for referencing context. I’m not a > C specialist but this seems to me at least not ok. > > I’m addressing the developers who used library in Swift projects, how did > you handle this situation ? > > > > Best regards, > Stefan > > > > > _______________________________________________ > Visit our blog: http://blog.pjsip.org > > pjsip mailing list > pjsip@lists.pjsip.org > http://lists.pjsip.org/mailman/listinfo/pjsip_lists.pjsip.org >