How do I announce a Bonjour service?


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)
{class} function dataFromTXTRecordDictionary(txtDictionary: NSDictionary): NSData; cdecl;
{class} function dictionaryFromTXTRecordData(txtData: NSData): NSDictionary; cdecl;
NSNetService = interface(NSObject)
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;
TNSNetService = class(TOCGenericImport<NSNetServiceClass, NSNetService>) end;


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

function TsdBonjourAnnouncerMac.Activate: Boolean;

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));

procedure TsdBonjourAnnouncerMac.DeActivate;

Comments are closed.