Home > Software design >  Delphi iOS MultipeerConnectivity InvitationHandler causes Access Violation
Delphi iOS MultipeerConnectivity InvitationHandler causes Access Violation

Time:08-01

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;
  • Related