How do I announce a Bonjour service?

194 Views Asked by At

I am trying to implement code that announces a Bonjour service on OSX. Out of the box, there isn't a direct way to do this.

In Macapi.Foundation are the following interfaces: NSNetServiceClass and NSNetService. Then there is the wrapper class TNSNetService. These are the interfaces and class that should let me announce a service.

In my class TsdBonjourAnnouncerMac, I have an activate() method which announces the service. I followed the same code template as creating a Bonjour listener, which works fine. However this code crashes.

The line of code INetService := TNSNetService.Wrap(TNSNetService.OCClass.alloc); is raising an Access Violation. TNSNetService.OCClass.alloc is the offender.

I don't know how to fix this.

I found this: Using OS X APIs directly from Delphi. It shows a slightly different process. I tried using it, but was not able to call any of the methods in NSNetService since they aren't class methods.

How can I get this to work?

      NSNetServiceClass = interface(NSObjectClass)
        ['{450D03AC-1380-44BA-B4C3-2D30DACACA43}']
        {class} function dataFromTXTRecordDictionary(txtDictionary: NSDictionary): NSData; cdecl;
        {class} function dictionaryFromTXTRecordData(txtData: NSData): NSDictionary; cdecl;
      end;
      NSNetService = interface(NSObject)
        ['{8FACC18E-5DFA-4526-A256-DBD7CF74B65C}']
        function TXTRecordData: NSData; cdecl;
        function addresses: NSArray; cdecl;
        function delegate: NSNetServiceDelegate; cdecl;
        function domain: NSString; cdecl;
        function getInputStream(inputStream: NSInputStream; outputStream: NSOutputStream): Boolean; cdecl;
        function hostName: NSString; cdecl;
        function name: NSString; cdecl;
        function port: NSInteger; cdecl;
        function protocolSpecificInformation: NSString; cdecl;
        procedure publish; cdecl;
        procedure publishWithOptions(options: NSNetServiceOptions); cdecl;
        procedure removeFromRunLoop(aRunLoop: NSRunLoop; forMode: NSString); cdecl;
        procedure resolve; cdecl;
        procedure resolveWithTimeout(timeout: NSTimeInterval); cdecl;
        procedure scheduleInRunLoop(aRunLoop: NSRunLoop; forMode: NSString); cdecl;
        procedure setDelegate(delegate: NSNetServiceDelegate); cdecl;
        procedure setProtocolSpecificInformation(specificInformation: NSString); cdecl;
        function setTXTRecordData(recordData: NSData): Boolean; cdecl;
        procedure startMonitoring; cdecl;
        procedure stop; cdecl;
        procedure stopMonitoring; cdecl;
      end;
      TNSNetService = class(TOCGenericImport<NSNetServiceClass, NSNetService>)  end;

 //****************************************************************************//

    TsdBonjourAnnouncerMac = class(TsdBonjourAnnouncerBase)
    private
        IDelegate:   NSNetServiceDelegate;
        INetService: NSNetService;
    protected
        function  Activate: Boolean; override;
        procedure DeActivate; override;
    public
    end;

function TsdBonjourAnnouncerMac.Activate: Boolean;
begin
    inherited;
    
    Result := True;
    INetService := TNSNetService.Wrap(TNSNetService.OCClass.alloc); // Raises access violation

    // More code to initialize

    // Set the delegate 
    
    IDelegate := TsdServiceDelegate.Create;
    
    INetService.setDelegate(NSNetServiceDelegate((IDelegate as ILocalObject).GetObjectID));
    INetService.publish;
end;
    
procedure TsdBonjourAnnouncerMac.DeActivate;
begin
end;
0

There are 0 best solutions below