zig-objc/README.md

102 lines
3.2 KiB
Markdown
Raw Normal View History

2023-01-02 14:59:39 -08:00
# zig-objc - Objective-C Runtime Bindings for Zig
zig-objc allows Zig to call Objective-C using the macOS
[Objective-C runtime](https://developer.apple.com/documentation/objectivec/objective-c_runtime?language=objc).
2023-01-02 15:03:07 -08:00
**Project Status:** This library does not currently have 100% coverage over the Objective-C
2023-01-02 14:59:39 -08:00
runtime, but supports enough features to be useful. I use this library in
shipping code that I run every day.
2023-01-02 15:03:07 -08:00
## Features
2023-01-02 14:59:39 -08:00
* Classes:
- Find classes
- Read property metadata
- Call methods
2023-10-20 22:43:44 -07:00
- Create subclasses
- Add methods
- Replace methods
- Add instance variables
2023-01-02 14:59:39 -08:00
* Objects:
- Class or class name for object
- Read and write properties
2023-10-20 22:43:44 -07:00
- Read and write instance variables
2023-01-02 14:59:39 -08:00
- Call methods
2023-10-20 22:43:44 -07:00
- 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
2023-01-02 14:59:39 -08:00
* 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.
```zig
const objc = @import("objc");
pub fn macosVersionAtLeast(major: i64, minor: i64, patch: i64) bool {
/// Get the objc class from the runtime
2023-10-20 22:50:33 -07:00
const NSProcessInfo = objc.getClass("NSProcessInfo").?;
2023-01-02 14:59:39 -08:00
/// Call a class method with no arguments that returns another objc object.
2023-10-20 22:50:33 -07:00
const info = NSProcessInfo.msgSend(objc.Object, "processInfo", .{});
2023-01-02 14:59:39 -08:00
/// Call an instance method that returns a boolean and takes a single
/// argument.
2023-10-20 22:50:33 -07:00
return info.msgSend(bool, "isOperatingSystemAtLeastVersion:", .{
2023-01-02 14:59:39 -08:00
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
2024-11-03 14:57:58 -08:00
Add this repository to your `build.zig.zon` file. Then:
2023-01-02 14:59:39 -08:00
```zig
pub fn build(b: *std.build.Builder) !void {
// ... other stuff
2024-11-03 14:57:58 -08:00
exe.root_module.addImport("obcj", b.dependency("zig_objc", .{
.target = target,
.optimize = optimize,
}).module("objc"));
2023-01-02 14:59:39 -08:00
}
```
2023-01-02 15:03:07 -08:00
2024-11-03 15:09:38 -08:00
Note that `zig-objc` will find and link to headers from the target SDK
(macOS, iOS, etc.) automatically by finding your Xcode installation. If
Xcode is not installed, you can add it manually but you must set the
`-Dadd-paths=false` flag.
2024-11-03 14:57:58 -08:00
**`zig-objc` only works with released versions of Zig.** We don't support
nightly versions because the Zig compiler is still changing too much.
2023-01-02 15:03:07 -08:00
## 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.