zig-objc allows Zig to call Objective-C using the macOS Objective-C runtime.
Project Status: This library does not currently have 100% coverage over the Objective-C runtime, but supports enough features to be useful. I use this library in shipping code that I run every day.
- Classes:
- Find classes
- Read property metadata
- Call methods
- Create subclasses
- Add methods
- Replace methods
- Add instance variables
- Objects:
- Class or class name for object
- Read and write properties
- Read and write instance variables
- Call methods
- Call superclass methods
- Protocols:
- Check conformance
- Read property metadata
- Blocks:
- Define and invoke blocks with captured values
- Pass blocks to C APIs which can then invoke your Zig code
- Autorelease pools
There is still a bunch of the runtime API that isn't supported. It wouldn't be hard work to add it, I just haven't needed it. For example: object instance variables, protocols, dynamically registering new classes, etc.
Feel free to open a pull request if you want additional features. Do not open issues to request features (only pull requests). I'm only going to add features I need, unless you open a pull request to add it yourself.
Here is an example that uses NSProcessInfo
to implement a function
macosVersionAtLeast
that returns true if the running macOS versions
is at least the given arguments.
const objc = @import("objc");
pub fn macosVersionAtLeast(major: i64, minor: i64, patch: i64) bool {
/// Get the objc class from the runtime
const NSProcessInfo = objc.getClass("NSProcessInfo").?;
/// Call a class method with no arguments that returns another objc object.
const info = NSProcessInfo.msgSend(objc.Object, "processInfo", .{});
/// Call an instance method that returns a boolean and takes a single
/// argument.
return info.msgSend(bool, "isOperatingSystemAtLeastVersion:", .{
NSOperatingSystemVersion{ .major = major, .minor = minor, .patch = patch },
});
}
/// This extern struct matches the Cocoa headers for layout.
const NSOperatingSystemVersion = extern struct {
major: i64,
minor: i64,
patch: i64,
};
Warning: This project follows the nightly releases of Zig and may not work with released versions of Zig until Zig stabilizes. I also am not promising API stability right now.
Use your favorite Zig package manager or vendor this repository, then add the package. For example in your build.zig:
const objc = @import("vendor/zig-objc/build.zig");
pub fn build(b: *std.build.Builder) !void {
// ... other stuff
exe.addPackage(objc.pkg);
}
Read the source code, it is well commented. If something isn't clear, please open an issue and I'll enhance the source code. Some familiarity with Objective-C concepts is expected for understanding the doc comments.