Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions build.zig.zon
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,7 @@
.lazy = true,
},
.zig_objc = .{
// mitchellh/zig-objc
.url = "https://deps.files.ghostty.org/zig_objc-f356ed02833f0f1b8e84d50bed9e807bf7cdc0ae.tar.gz",
.hash = "zig_objc-0.0.0-Ir_Sp5gTAQCvxxR7oVIrPXxXwsfKgVP7_wqoOQrZjFeK",
.path = "./pkg/zig-objc",
.lazy = true,
},
.zig_js = .{
Expand Down
10 changes: 8 additions & 2 deletions include/ghostty.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@
// isn't meant to be a general purpose embedding API (yet) so there hasn't
// been documentation or example work beyond that.
//
// The only consumer of this API is the macOS app, but the API is built to
// be more general purpose.
// cmux uses this API on both macOS and iOS. The iOS integration depends on
// manual surface I/O via ghostty_surface_config_s.io_mode, io_write_cb,
// ghostty_surface_process_output, and ghostty_surface_text_input.
#ifndef GHOSTTY_H
#define GHOSTTY_H

Expand Down Expand Up @@ -1084,6 +1085,7 @@ bool ghostty_surface_needs_confirm_quit(ghostty_surface_t);
bool ghostty_surface_process_exited(ghostty_surface_t);
void ghostty_surface_refresh(ghostty_surface_t);
void ghostty_surface_draw(ghostty_surface_t);
void ghostty_surface_draw_now(ghostty_surface_t);
void ghostty_surface_set_content_scale(ghostty_surface_t, double, double);
void ghostty_surface_set_focus(ghostty_surface_t, bool);
void ghostty_surface_set_occlusion(ghostty_surface_t, bool);
Expand All @@ -1098,6 +1100,7 @@ bool ghostty_surface_key_is_binding(ghostty_surface_t,
ghostty_input_key_s,
ghostty_binding_flags_e*);
void ghostty_surface_text(ghostty_surface_t, const char*, uintptr_t);
void ghostty_surface_text_input(ghostty_surface_t, const char*, uintptr_t);
void ghostty_surface_preedit(ghostty_surface_t, const char*, uintptr_t);
void ghostty_surface_process_output(ghostty_surface_t, const char*, uintptr_t);
bool ghostty_surface_mouse_captured(ghostty_surface_t);
Expand Down Expand Up @@ -1133,6 +1136,9 @@ bool ghostty_surface_read_selection(ghostty_surface_t, ghostty_text_s*);
bool ghostty_surface_read_text(ghostty_surface_t,
ghostty_selection_s,
ghostty_text_s*);
bool ghostty_surface_read_text_html(ghostty_surface_t,
ghostty_selection_s,
ghostty_text_s*);
void ghostty_surface_free_text(ghostty_surface_t, ghostty_text_s*);

#ifdef __APPLE__
Expand Down
2 changes: 1 addition & 1 deletion macos/Sources/Ghostty/Ghostty.Surface.swift
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ extension Ghostty {

text.withCString { ptr in
// len includes the null terminator so we do len - 1
ghostty_surface_text(surface, ptr, UInt(len - 1))
ghostty_surface_text_input(surface, ptr, UInt(len - 1))
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Keep non-keyboard text on paste-safe path

Switching sendText to ghostty_surface_text_input removes paste encoding/protection for every caller of this method; unlike ghostty_surface_text, the new path skips bracketed-paste framing and control-byte filtering. In this codebase, drag-and-drop text is routed through insertText into sendText (SurfaceView_AppKit.performDragOperation), so dropped content now reaches the terminal as raw typed input and can execute multiline/untrusted payloads immediately.

Useful? React with 👍 / 👎.

}
}

Expand Down
24 changes: 19 additions & 5 deletions pkg/apple-sdk/build.zig
Original file line number Diff line number Diff line change
Expand Up @@ -41,14 +41,28 @@ pub fn addPaths(
});

if (!gop.found_existing) {
const sdkroot_override = std.process.getEnvVarOwned(b.allocator, "SDKROOT") catch |err| switch (err) {
error.EnvironmentVariableNotFound => null,
else => return err,
};
defer if (sdkroot_override) |sdkroot| b.allocator.free(sdkroot);

// Detect our SDK using the "findNative" Zig stdlib function.
// This is really important because it forces using `xcrun` to
// find the SDK path.
const libc = try std.zig.LibCInstallation.findNative(.{
.allocator = b.allocator,
.target = &step.rootModuleTarget(),
.verbose = false,
});
const libc = libc: {
if (sdkroot_override) |sdkroot| {
var libc: std.zig.LibCInstallation = .{};
libc.include_dir = try std.fs.path.join(b.allocator, &.{ sdkroot, "usr", "include" });
libc.sys_include_dir = try std.fs.path.join(b.allocator, &.{ sdkroot, "usr", "include" });
break :libc libc;
Comment on lines +54 to +58
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Partially-populated LibCInstallation written to libc.txt

When SDKROOT is set, only include_dir and sys_include_dir are populated; fields like crt_dir, lib_dir, gcc_dir, and headers_dir remain null. LibCInstallation.render() will emit empty values for those fields in the generated libc.txt.

In practice this is fine for ARM macOS targets (no CRT/libc stubs needed), but it's worth documenting the assumption with a comment, e.g.:

// SDKROOT override: only header paths are required for Apple Silicon targets.
// CRT/lib/gcc dirs are not needed and left null.

If this ever needs to work on other Apple targets (iOS device, tvOS, etc.) the missing crt_dir/lib_dir may cause linker errors.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Comment on lines +54 to +58
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Gate SDKROOT override by target SDK

Using SDKROOT unconditionally here makes one environment value override SDK discovery for every Apple target in the same zig build process. In this commit, GhosttyXCFramework now builds macOS, iOS, and iOS-simulator variants together (src/build/GhosttyXCFramework.zig), so exporting SDKROOT to a macOS SDK causes iOS/simulator compiles to pick macOS include/framework paths and fail. The override should only be used when it matches the current target SDK (or be made target-specific), otherwise fall back to findNative/xcrun per target.

Useful? React with 👍 / 👎.

}
break :libc try std.zig.LibCInstallation.findNative(.{
.allocator = b.allocator,
.target = &step.rootModuleTarget(),
.verbose = false,
});
};

// Render the file compatible with the `--libc` Zig flag.
var stream: std.io.Writer.Allocating = .init(b.allocator);
Expand Down
13 changes: 10 additions & 3 deletions pkg/macos/iosurface/iosurface.zig
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ pub const IOSurface = opaque {
};

pub fn init(properties: Properties) Allocator.Error!*IOSurface {
// Metal requires IOSurface row bytes to be aligned (64-byte is safe).
const row_bytes: c_int = @intCast(
(@as(usize, @intCast(properties.width)) * @as(usize, @intCast(properties.bytes_per_element)) + 63) & ~@as(usize, 63),
);
var w = try foundation.Number.create(.int, &properties.width);
defer w.release();
var h = try foundation.Number.create(.int, &properties.height);
Expand All @@ -28,15 +32,18 @@ pub const IOSurface = opaque {
defer pf.release();
var bpe = try foundation.Number.create(.int, &properties.bytes_per_element);
defer bpe.release();
var rb = try foundation.Number.create(.int, &row_bytes);
defer rb.release();

var properties_dict = try foundation.Dictionary.create(
&[_]?*const anyopaque{
c.kIOSurfaceWidth,
c.kIOSurfaceHeight,
c.kIOSurfacePixelFormat,
c.kIOSurfaceBytesPerElement,
c.kIOSurfaceBytesPerRow,
},
&[_]?*const anyopaque{ w, h, pf, bpe },
&[_]?*const anyopaque{ w, h, pf, bpe, rb },
);
defer properties_dict.release();

Expand Down Expand Up @@ -84,14 +91,14 @@ pub const IOSurface = opaque {
}

pub inline fn lock(self: *IOSurface) void {
c.IOSurfaceLock(
_ = c.IOSurfaceLock(
@ptrCast(self),
0,
null,
);
}
pub inline fn unlock(self: *IOSurface) void {
c.IOSurfaceUnlock(
_ = c.IOSurfaceUnlock(
@ptrCast(self),
0,
null,
Expand Down
21 changes: 21 additions & 0 deletions pkg/zig-objc/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2023 Mitchell Hashimoto

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
101 changes: 101 additions & 0 deletions pkg/zig-objc/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
# 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).

**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.
Comment on lines +46 to +47
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Fix grammar in the example description.

Line 46-Line 47 should use singular phrasing: “running macOS version is…”.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/zig-objc/README.md` around lines 46 - 47, The example description for
macosVersionAtLeast uses plural "versions"; change the sentence to singular
phrasing so it reads "running macOS version is at least the given arguments."
Update the README example that mentions macosVersionAtLeast to use "running
macOS version is…" (referencing the macosVersionAtLeast symbol) to correct the
grammar.


```zig
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

Add this repository to your `build.zig.zon` file. Then:

```zig
pub fn build(b: *std.build.Builder) !void {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify build API usage patterns in this repository.
rg -nP --type=zig 'pub fn build\s*\(\s*b:\s*\*std\.Build\s*\)'
rg -nP --type=zig 'std\.build\.Builder'

Repository: manaflow-ai/ghostty

Length of output: 2035


🏁 Script executed:

cat -n pkg/zig-objc/README.md | sed -n '70,90p'

Repository: manaflow-ai/ghostty

Length of output: 659


Update the build function signature in the usage example to use the current Zig API.

Line 79 documents *std.build.Builder, which is outdated. All build scripts in this repository (and current Zig versions) use *std.Build. Users copying this snippet will encounter build errors.

Suggested fix
-pub fn build(b: *std.build.Builder) !void {
+pub fn build(b: *std.Build) !void {
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
pub fn build(b: *std.build.Builder) !void {
pub fn build(b: *std.Build) !void {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/zig-objc/README.md` at line 79, The README usage example shows an
outdated build signature using "*std.build.Builder"; update the example to the
current Zig API by changing the build function parameter type to "*std.Build"
(i.e., the "build" function signature used in the snippet should accept
*std.Build), and scan any other examples in the README that reference
std.build.Builder to ensure they use std.Build consistently so users won't hit
build errors when copying the snippet.

// ... other stuff

exe.root_module.addImport("objc", b.dependency("zig_objc", .{
.target = target,
.optimize = optimize,
}).module("objc"));
}
```

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.

**`zig-objc` only works with released versions of Zig.** We don't support
nightly versions because the Zig compiler is still changing too much.

## 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.
99 changes: 99 additions & 0 deletions pkg/zig-objc/build.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
const std = @import("std");

pub fn build(b: *std.Build) !void {
const optimize = b.standardOptimizeOption(.{});
const target = b.standardTargetOptions(.{});
const add_paths = b.option(
bool,
"add-paths",
"add apple SDK paths from Xcode installation",
) orelse true;

const objc = b.addModule("objc", .{
.root_source_file = b.path("src/main.zig"),
.target = target,
.optimize = optimize,
});
if (add_paths) try addAppleSDK(b, objc);
objc.linkSystemLibrary("objc", .{});
objc.linkFramework("Foundation", .{});

const tests = b.addTest(.{
.name = "objc-test",
.root_module = b.createModule(.{
.root_source_file = b.path("src/main.zig"),
.target = target,
.optimize = optimize,
}),
});
tests.linkSystemLibrary("objc");
tests.linkFramework("Foundation");
tests.linkFramework("AppKit"); // Required by 'tagged pointer' test.
try addAppleSDK(b, tests.root_module);
Comment on lines +21 to +32
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Test module doesn't respect add_paths option.

The objc module at line 17 conditionally calls addAppleSDK based on the add-paths option, but the test module at line 32 always calls addAppleSDK unconditionally. This inconsistency could cause test builds to fail when add-paths=false is set.

🔧 Suggested fix
     tests.linkSystemLibrary("objc");
     tests.linkFramework("Foundation");
     tests.linkFramework("AppKit"); // Required by 'tagged pointer' test.
-    try addAppleSDK(b, tests.root_module);
+    if (add_paths) try addAppleSDK(b, tests.root_module);
     b.installArtifact(tests);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const tests = b.addTest(.{
.name = "objc-test",
.root_module = b.createModule(.{
.root_source_file = b.path("src/main.zig"),
.target = target,
.optimize = optimize,
}),
});
tests.linkSystemLibrary("objc");
tests.linkFramework("Foundation");
tests.linkFramework("AppKit"); // Required by 'tagged pointer' test.
try addAppleSDK(b, tests.root_module);
const tests = b.addTest(.{
.name = "objc-test",
.root_module = b.createModule(.{
.root_source_file = b.path("src/main.zig"),
.target = target,
.optimize = optimize,
}),
});
tests.linkSystemLibrary("objc");
tests.linkFramework("Foundation");
tests.linkFramework("AppKit"); // Required by 'tagged pointer' test.
if (add_paths) try addAppleSDK(b, tests.root_module);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/zig-objc/build.zig` around lines 21 - 32, The test target named by the
tests variable calls addAppleSDK unconditionally (try addAppleSDK(b,
tests.root_module)), which differs from the objc module that only calls
addAppleSDK when the build option "add-paths" is enabled; change the test logic
to guard the addAppleSDK call with the same add-paths check used by the objc
module so tests respect the add-paths option (i.e., only call addAppleSDK(b,
tests.root_module) when the add-paths flag is true).

Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot Mar 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Honor the add-paths option for the tests module too; otherwise zig build test -Dadd-paths=false still tries to locate the Apple SDK and fails without Xcode.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At pkg/zig-objc/build.zig, line 32:

<comment>Honor the add-paths option for the tests module too; otherwise `zig build test -Dadd-paths=false` still tries to locate the Apple SDK and fails without Xcode.</comment>

<file context>
@@ -0,0 +1,99 @@
+    tests.linkSystemLibrary("objc");
+    tests.linkFramework("Foundation");
+    tests.linkFramework("AppKit"); // Required by 'tagged pointer' test.
+    try addAppleSDK(b, tests.root_module);
+    b.installArtifact(tests);
+
</file context>
Fix with Cubic

b.installArtifact(tests);

const test_step = b.step("test", "Run tests");
const tests_run = b.addRunArtifact(tests);
test_step.dependOn(&tests_run.step);
}

/// Add the SDK framework, include, and library paths to the given module.
/// The module target is used to determine the SDK to use so it must have
/// a resolved target.
///
/// The Apple SDK is determined based on the build target and found using
/// xcrun, so it requires a valid Xcode installation.
pub fn addAppleSDK(b: *std.Build, m: *std.Build.Module) !void {
// The cache. This always uses b.allocator and never frees memory
// (which is idiomatic for a Zig build exe).
const Cache = struct {
const Key = struct {
arch: std.Target.Cpu.Arch,
os: std.Target.Os.Tag,
abi: std.Target.Abi,
};

var map: std.AutoHashMapUnmanaged(Key, ?[]const u8) = .{};
};

const target = m.resolved_target.?.result;
const gop = try Cache.map.getOrPut(b.allocator, .{
.arch = target.cpu.arch,
.os = target.os.tag,
.abi = target.abi,
});

// This executes `xcrun` to get the SDK path. We don't want to execute
// this multiple times so we cache the value.
if (!gop.found_existing) {
const sdkroot_override = std.process.getEnvVarOwned(b.allocator, "SDKROOT") catch |err| switch (err) {
error.EnvironmentVariableNotFound => null,
else => return err,
};
defer if (sdkroot_override) |sdkroot| b.allocator.free(sdkroot);

if (sdkroot_override) |sdkroot| {
gop.value_ptr.* = try b.allocator.dupe(u8, sdkroot);
Comment on lines +75 to +76
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Gate SDKROOT override by resolved Apple target

The SDK override is applied unconditionally for every target in this dependency, so a single SDKROOT value is reused even when the build includes multiple Apple SDKs. In the same Zig invocation we build macOS, iOS, and iOS-simulator artifacts (see src/build/GhosttyXCFramework.zig), so exporting a macOS SDKROOT causes the iOS variants of zig_objc to pick macOS headers/framework paths and fail. The override should only be used when it matches m.resolved_target, otherwise fall back to per-target SDK discovery.

Useful? React with 👍 / 👎.

} else {
gop.value_ptr.* = std.zig.system.darwin.getSdk(
b.allocator,
&m.resolved_target.?.result,
);
}
}

// The active SDK we want to use
const path = gop.value_ptr.* orelse return switch (target.os.tag) {
// Return a more descriptive error. Before we just returned the
// generic error but this was confusing a lot of community members.
// It costs us nothing in the build script to return something better.
.macos => error.XcodeMacOSSDKNotFound,
.ios => error.XcodeiOSSDKNotFound,
.tvos => error.XcodeTVOSSDKNotFound,
.watchos => error.XcodeWatchOSSDKNotFound,
else => error.XcodeAppleSDKNotFound,
};
m.addSystemFrameworkPath(.{ .cwd_relative = b.pathJoin(&.{ path, "System/Library/Frameworks" }) });
m.addSystemIncludePath(.{ .cwd_relative = b.pathJoin(&.{ path, "usr/include" }) });
m.addLibraryPath(.{ .cwd_relative = b.pathJoin(&.{ path, "usr/lib" }) });
}
13 changes: 13 additions & 0 deletions pkg/zig-objc/build.zig.zon
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
.{
.name = .zig_objc,
.version = "0.0.0",
.fingerprint = 0x8a91772ba7d2bf22,
.paths = .{
"src/",
"build.zig",
"build.zig.zon",
"README.md",
"LICENSE",
},
.dependencies = .{},
}
17 changes: 17 additions & 0 deletions pkg/zig-objc/src/autorelease.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
const std = @import("std");

pub const AutoreleasePool = opaque {
/// Create a new autorelease pool. To clean it up, call deinit.
pub inline fn init() *AutoreleasePool {
return @ptrCast(objc_autoreleasePoolPush().?);
}

pub inline fn deinit(self: *AutoreleasePool) void {
objc_autoreleasePoolPop(self);
}
};

// I'm not sure if these are internal or not... they aren't in any headers,
// but its how autorelease pools are implemented.
extern "c" fn objc_autoreleasePoolPush() ?*anyopaque;
extern "c" fn objc_autoreleasePoolPop(?*anyopaque) void;
Loading
Loading