I´m trying to get the MultiPeerConnectivity-Framework to work in Delphi. Everything works fine until the Point where i need to call the invitationHandler in the MCNearbyServiceAdvertiserDelegate.
procedure TMCNearbyServiceAdvertiserDelegate.advertiser(advertiser: MCNearbyServiceAdvertiser;
didReceiveInvitationFromPeer: MCPeerID; withContext: NSData;
invitationHandler: TMCNearbyServiceAdvertiserDelegateBlockMethod1);
The Peers are finding each other and are exchanging Discoveryinfo. The 'Client' uses the MCNearbyServiceBrowser to connect to the MCNearbyServiceAdvertiser in the 'Server'.
When calling the invitationHandler-BlockMethod an AccessViolation is thrown :(
Now i´ve tried using the method imp_implementationWithBlock to get the code for the Handler:
procedure TMCNearbyServiceAdvertiserDelegate.advertiser(advertiser: MCNearbyServiceAdvertiser;
didReceiveInvitationFromPeer: MCPeerID; withContext: NSData;
invitationHandler: TMCNearbyServiceAdvertiserDelegateBlockMethod1);
var
MainForm: TMainForm;
aImp: procedure(accept: Boolean; session: MCSession); cdecl;
begin
MainForm := application.MainForm as TMainForm;
if MainForm.fSession = nil then
begin
MainForm.fSession := TMCSession.Alloc;
MainForm.fSession.initWithPeer(MainForm.fPeerId);
MainForm.fSessionDelegate := TMCSessionDelegate.Create;
MainForm.fSession.setDelegate(MainForm.fSessionDelegate.GetObjectID);
end;
@aImp := imp_implementationWithBlock(invitationHandler);
aImp(True, MainForm.fSession);
imp_removeBlock(@aImp);
end;
But with that Approch i get an error because the invitationHandler is no Pointer i guess.
Definition of the TMCNearbyServiceAdvertiserDelegateBlockMethod1 in the iOSApi.MultiPeerConnectivity.pas from Kastri:
TMCNearbyServiceAdvertiserDelegateBlockMethod1 = procedure(accept: Boolean; session: MCSession) of object;
i hope thats not to much information a once. Any help toward calling that invitationHandler the right way would be very appreciated!
CodePudding user response:
Finally solved it!
I found a similar case in the System.Net.HttpClient.Mac
unit in Delphi, in the TMacConnectionDataDelegate.URLSessionTaskDidReceiveChallengeCompletionHandler
method. Block handlers need to include a second parameter declared as a Pointer
. I cannot remember why this is, I just know it works :-) The session
parameter also needs to be a Pointer
, and use the NSObjectToID
method to turn your reference into a pointer for that parameter.
As per my comments in the question, you need to change the block method type to a Pointer
(instead of TMCNearbyServiceAdvertiserDelegateBlockMethod1
) in the delegate interface and the implementation, and declare the block handler method as discussed above, so this should work for you:
procedure TMCNearbyServiceAdvertiserDelegate.advertiser(advertiser: MCNearbyServiceAdvertiser;
didReceiveInvitationFromPeer: MCPeerID; withContext: NSData;
invitationHandler: Pointer);
var
MainForm: TMainForm;
aImp: procedure(accept: Boolean; ignored: Pointer; session: Pointer); cdecl;
begin
MainForm := application.MainForm as TMainForm;
if MainForm.fSession = nil then
begin
MainForm.fSession := TMCSession.Alloc;
MainForm.fSession.initWithPeer(MainForm.fPeerId);
MainForm.fSessionDelegate := TMCSessionDelegate.Create;
MainForm.fSession.setDelegate(MainForm.fSessionDelegate.GetObjectID);
end;
@aImp := imp_implementationWithBlock(invitationHandler);
aImp(True, nil, NSObjectToID(MainForm.fSession));
imp_removeBlock(@aImp);
end;