Objective-C runtime bindings for Zig (Zig calling ObjC).
Find a file
Mitchell Hashimoto c9dc8d2505
update zig
2024-04-12 10:30:21 -07:00
.github/workflows ci: use macos tester 2023-10-20 15:54:57 -07:00
src fix!: avoid "comptime var" error by returning array instead of slice 2024-04-12 10:01:04 +01:00
.envrc
.gitignore
.gitmodules use zig package manager 2023-08-03 16:54:20 -07:00
build.zig fix!: avoid "comptime var" error by returning array instead of slice 2024-04-12 10:01:04 +01:00
build.zig.zon fix!: avoid "comptime var" error by returning array instead of slice 2024-04-12 10:01:04 +01:00
flake.lock update zig 2024-04-12 10:30:21 -07:00
flake.nix update zig 2023-06-30 09:49:12 -07:00
LICENSE
README.md update README for new API 2023-10-20 22:50:33 -07:00
shell.nix

zig-objc - Objective-C Runtime Bindings for Zig

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.

Features

  • 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.

Example

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,
};

Usage

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

Documentation

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.