Is possible to use Mac OS X XPC like IPC to exchange messages between processes? How?

后端 未结 3 1264
孤街浪徒
孤街浪徒 2021-01-30 02:55

According to Apple, the new XPC Services API, introduced in Lion, provides a lightweight mechanism for basic interprocess communication integrated with Grand Central Dispatch (G

3条回答
  •  清歌不尽
    2021-01-30 03:09

    Alright for anyone that has been struggling with this, I was finally able to 100% get communication working between two application processes, using NSXPCConnection

    The key to note is that you can only create an NSXPCConnection to three things.

    1. An XPCService. You can connect to an XPCService strictly through a name
    2. A Mach Service. You can also connect to a Mach Service strictly through a name
    3. An NSXPCEndpoint. This is what we're looking for, to communicate between two application processes.

    The problem being that we can't directly transfer an NSXPCListenerEndpoint from one application to another.

    It involved creating a machservice Launch Agent (See this example for how to do that) that held an NSXPCListenerEndpoint property. One application can connect to the machservice, and set that property to it's own [NSXPCListener anonymousListener].endpoint

    Then the other application can connect to the machservice, and ask for that endpoint.

    Then using that endpoint, an NSXPCConnection can be created, which successfully established a bridge between the two applications. I have tested sending objects back and forth, and it all works as expected.

    Note that if your application is sandboxed, you will have to create an XPCService, as a middle man between your Application and the Machservice

    I'm pretty pumped that I got this working-- I'm fairly active in SO, so if anybody is interested in source code, just add a comment and I can go through the effort to post more details

    Some hurdles I came across:

    You have to launch your machservice, these are the lines:

       OSStatus                    err;
       AuthorizationExternalForm   extForm;
    
       err = AuthorizationCreate(NULL, NULL, 0, &self->_authRef);
       if (err == errAuthorizationSuccess) {
          NSLog(@"SUCCESS AUTHORIZING DAEMON");
       }
       assert(err == errAuthorizationSuccess);
    
       Boolean             success;
       CFErrorRef          error;
    
       success = SMJobBless(
                            kSMDomainSystemLaunchd,
                            CFSTR("DAEMON IDENTIFIER HERE"),
                            self->_authRef,
                            &error
                            );
    

    Also, every time you rebuild your daemon, you have to unload the previous launch agent, with these bash commands:

    sudo launchctl unload /Library/LaunchDaemons/com.example.apple-samplecode.EBAS.HelperTool.plist
    sudo rm /Library/LaunchDaemons/com.example.apple-samplecode.EBAS.HelperTool.plist
    sudo rm /Library/PrivilegedHelperTools/com.example.apple-samplecode.EBAS.HelperTool
    

    (With your corresponding identifiers, of course)

提交回复
热议问题