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;