Mix NSXPCConnection and xpc C API - objective-c

I am working with XPC services using NSXPCConnection wrapper, and since the Objective-C wrapper can't handle IOSurfaceRef objects, I would like to make some direct functions calls to the C API defined in xpc.h. But I can't find a way to retrieve the underlying xpc_connection_t reference (as I can see in NSXPCConnection.h, there is a private ivar called _xconnection that could be the reference I need).
Am I missing something stupid, or can't the Objective-C wrapper and the C API simply be used together?

Nope, but XPCKit offers such a conversion mechanism AND it's 10.7 compatible.

Related

How to call function using objc in Rust

I want to run a function of Cocoa's Quartz Window Services on Mac called CGWindowListCopyWindowInfo using a library called objc from Rust, is it possible?
I can't figure out how to run function it with send_msg!.
First, you're linking to the Swift version of the API, you really want the objective C version.
Second, Objective-C is for "methods" on objects, that is why send_msg! takes a subject (obj). CGWindowListCopyWindowInfo is part of a "core" service, which means it's pretty much straight C. Now I don't know if there are bindings for that, apparently Servo once maintained CG bindings but it seems like they're deprecated. You can probably BYO as if you were binding to a regular C library (by hand or using bindgen).
I would recommend learning how macOS APIs and frameworks work first, though.

How do you use MTLSharedTextureHandle or MTLSharedEventHandle with the C XPC interface on macOS?

TL;DR: How do you encode and decode an MTLSharedTextureHandle and MTLSharedEventHandler such that it can be transported across an XPC connection inside an xpc_dictionary?
A macOS application I'm working on makes extensive use of XPC services and was implemented using the C-based API. (i.e.: xpc_main, xpc_connection, xpc_dictionary...) This made sense at the time because certain objects, like IOSurfaces, did not support NSCoding/NSSecureCoding and had to be passed using IOSurfaceCreateXPCObject.
In macOS 10.14, Apple introduced new classes for sharing Metal textures and events between processes: MTLSharedTextureHandle and MTLSharedEventHandle. These classes support NSSecureCoding but they don't appear to have a counter-part in the C-XPC interface for encoding/decoding them.
I thought I could use something like [NSKeyedArchiver archivedDataWithRootObject:requiringSecureCoding:error] to just convert them to NSData objects, which can then be stored in an xpc_dictionary, but when I try and do that, I get the following exception:
Caught exception during archival:
This object may only be encoded by an NSXPCCoder.
(NSXPCCoder is a private class.)
This happens for both MTLSharedTextureHandle and MTLSharedEventHandle. I could switch over to using the new NSXPCConnection API but I've already got an extensive amount of code built on the C-interface, so I'd rather not have to make the switch.
Is there any way to archive either of those two classes into a payload that can be stored in an xpc_dictionary for transfer between the service and the client?
MTLSharedTextureHandle only works with NSXPCConnection. If you're creating the texture from an IOSurface you can share the surface instead which is effectively the same thing. Make sure you are using the same GPU (same id<MTLDevice>) in both processes.
There is no workaround for MTLSharedEventHandle using public API.
I recommend switching to NSXPCConnection if you can. Unfortunately there isn't a good story for partially changing over using public API, you'll have to do it all at once or split your XPC service into two separate services.

Creating an Objective-C API

I have never made an API in objective-c, and need to do this now.
The "idea" is that I build an API which can be implemented into other applications. Much like Flurry, only for other purposes.
When starting the API, an username, password and mode should be entered. The mode should either be LIVE or BETA (I guess this should be an NSString(?)), then afterwards is should be fine with [MyAPI doSomething:withThisObject]; ect.
So to start it [MyAPI username:#"Username" password:#"Password" mode:#"BETA"];
Can anyone help me out with some tutorials and pointer on how to learn this best?
It sounds like what you want to do is build a static library. This is a compiled .a file containing object code that you'll distribute to a client along with a header file containing the interface. This post is a little outdated but has some good starting points. Or, if you don't mind giving away your source code, you could just deliver a collection of source files to your client.
In terms of developing the API itself, it should be very similar to the way you'd design interfaces and implementations of Objective-C objects in your own apps. You'll have a MyAPI class with functions for initialization, destruction, and all the functionality you want. You could also have multiple classes with different functionality if the interface is complex. Because you've capitalized MyAPI in your code snippet, it looks like you want to use it by calling the class rather than an instance of the class - which is a great strategy if you think you'll only ever need one instance. To accomplish this you can use the singleton pattern.
Because you've used a username and password, I imagine your API will interface with the web internally. I've found parsing JSON to be very straightforward in Objective-C - it's easy to send requests and get information from a server.
Personally I would use an enum of unsigned ints rather than a NSString just because it simplifies comparisons and such. So you could do something like:
enum {
MYAPI_MODE_BETA,
MYAPI_MODE_LIVE,
NUM_MYAPI_MODES
};
And then call:
[MyAPI username:#"Username" password:#"Password" mode:MYAPI_MODE_BETA];
Also makes it easy to check if they've supplied a valid mode. (Must be less than NUM_MYAPI_MODES.)
Good luck!

How to push data from unmanaged to managed code?

I am using a C++/CLI Wrapper to access a purely C++ library (-> unmanaged) from a C# framework (-> managed). I want to build in a mechanism which enables the C++ library to push information about its status towards the framework. In my understanding this means that I will have to call at least a managed function from unmanaged code at some point. Is this possible and how can I achieve this?
Many thanks for your help!
Best regards,
Jakob
Use a delegate to let unmanaged code call a managed method. Marshal::GetFunctionPointerForDelegate() creates a stub that takes care of the transition, calling an instance method is supported. You can cast the returned pointer to a function pointer usable by the unmanaged code.
You'll find a full code sample in this answer.
I would recommend using a (managed) event for this. You could have your C++ wrapper call a method on your C++/CLI generated class which raises the event.
The event can easily be subscribed to from the C# side, and used like any other C# based event.

Helper functions in Cocoa

What is the standard way of incorporating helper/utility functions in Obj-C classes?
I.e. General purpose functions which are used throughout the application and called by more than 1 class.
Can an Obj-C method exist outside of a class, or does it need to be a C function for it to have this kind of behaviour?
I would group similar functions as static methods in a helper class. These can then be called using the classname rather the instance name. Static methods are defined with a + instead of the usual -.
like so:
#interface HelperClass: superclassname {
// instance variables - none if all methods are static.
}
+ (void) helperMethod: (int) parameter_varName;
#end
This would be called like so.
[HelperClass helperMethod: 10 ];
As this is static you do not init/alloc the class. This has the advantage of clearly grouping like Helper functions. You could use standalone C functions but as your Application gets larger it can become a right mess! Hope this helps.
Tony
I don't see why people are avoiding creating functions. Objective-C is a superset of C, which means that C is part of it. Moreover, it's completely integrated—there's no wall between them.
Create functions! It's fine! Foundation does it. Application Kit does it. Core Animation does it. Core Media does it.
I see no reason not to.
There are a number of options for this in Objective-C. First, since Obj-C is a strict superset of C, you can define all your library functions in a separate module (source file) and happily call them from any Obj-C object/code you already have. If you create an obj-c source file (.m file) you can then call back into/use objects.
If your generic functions are logically manipulating other, established objects (for instances, operates on an NSString), you can use categories to graph your functions on already existing classes (where that makes sense).
Finally, as Tony points out, you can create classes with static methods (although I like this option the least, personally). I tend to use a mix of one an two... adding categories where appropriate and using standard functions for others. I generally only make a new class where it makes sense to design a class.