diff --git a/examples/objective-c-macos/.gitignore b/examples/objective-c-macos/.gitignore
new file mode 100644
index 00000000..da2cb165
--- /dev/null
+++ b/examples/objective-c-macos/.gitignore
@@ -0,0 +1,5 @@
+/build/
+/build-*/
+/dist/
+/*.rsp
+/typephp_macos_hello
diff --git a/examples/objective-c-macos/Info.plist b/examples/objective-c-macos/Info.plist
new file mode 100644
index 00000000..a8541b7c
--- /dev/null
+++ b/examples/objective-c-macos/Info.plist
@@ -0,0 +1,26 @@
+
+
+
+
+ CFBundleDevelopmentRegion
+ en
+ CFBundleExecutable
+ typephp-macos-hello
+ CFBundleIdentifier
+ org.swoole.typephp.macos-hello
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundleName
+ TypePHP macOS Hello
+ CFBundlePackageType
+ APPL
+ CFBundleShortVersionString
+ 0.1.0
+ CFBundleVersion
+ 1
+ LSMinimumSystemVersion
+ 11.0
+ NSHighResolutionCapable
+
+
+
diff --git a/examples/objective-c-macos/README.md b/examples/objective-c-macos/README.md
new file mode 100644
index 00000000..ab1692a9
--- /dev/null
+++ b/examples/objective-c-macos/README.md
@@ -0,0 +1,40 @@
+# TypePHP macOS AppKit example
+
+This is a native macOS GUI application built from TypePHP and Objective-C++.
+TypePHP defines the window layout, application state, click behavior and event
+loop. Objective-C++ remains a thin platform bridge that exposes primitive AppKit
+operations. Clicking the native button returns a control ID to TypePHP, which
+updates the status label.
+
+Requirements:
+
+- macOS with Xcode Command Line Tools
+- PHP 8.4 or 8.5 built with the embed SAPI (`libphp.dylib`)
+- a matching PHPX build
+- `PHPX_HOME` pointing to the PHPX source tree
+
+Build from the TypePHP repository root:
+
+```sh
+export PHPX_HOME=/path/to/phpx
+php bin/tpc.php examples/objective-c-macos/project.yml --no-progress
+```
+
+Run the native executable:
+
+```sh
+./examples/objective-c-macos/typephp_macos_hello
+```
+
+To create a standard `.app` bundle that can be launched from Finder:
+
+```sh
+sh examples/objective-c-macos/package-app.sh
+open "examples/objective-c-macos/dist/TypePHP macOS Hello.app"
+```
+
+The project uses an `.mm` source because PHPX exposes a C++ API. Its project
+configuration enables ARC and links both AppKit and Foundation. This example is
+macOS-only; an iOS application would additionally require Xcode project and
+code-signing integration, so it is intentionally not mixed into this desktop
+example.
diff --git a/examples/objective-c-macos/objc-src/macos_bridge.mm b/examples/objective-c-macos/objc-src/macos_bridge.mm
new file mode 100644
index 00000000..d5764885
--- /dev/null
+++ b/examples/objective-c-macos/objc-src/macos_bridge.mm
@@ -0,0 +1,197 @@
+#include
+#include
+
+static NSString *to_ns_string(const php::Str &value)
+{
+ NSString *result = [[NSString alloc] initWithBytes:value.data()
+ length:value.length()
+ encoding:NSUTF8StringEncoding];
+ return result == nil ? @"" : result;
+}
+
+@interface TypePHPAppKitBridge : NSObject
+
+@property(nonatomic, strong) NSWindow *window;
+@property(nonatomic, strong) NSMutableDictionary *controls;
+@property(nonatomic) NSInteger nextControlId;
+@property(nonatomic) NSInteger pendingControlId;
+@property(nonatomic) BOOL running;
+
+- (void)controlActivated:(NSControl *)sender;
+
+@end
+
+@implementation TypePHPAppKitBridge
+
+- (instancetype)init
+{
+ self = [super init];
+ if (self != nil) {
+ self.controls = [[NSMutableDictionary alloc] init];
+ self.nextControlId = 1;
+ }
+ return self;
+}
+
+- (void)controlActivated:(NSControl *)sender
+{
+ self.pendingControlId = sender.tag;
+}
+
+- (void)windowWillClose:(NSNotification *)notification
+{
+ (void) notification;
+ self.running = NO;
+}
+
+@end
+
+static __strong TypePHPAppKitBridge *bridge = nil;
+
+static void install_application_menu(NSString *applicationName)
+{
+ NSMenu *menuBar = [[NSMenu alloc] init];
+ NSMenuItem *applicationMenuItem = [[NSMenuItem alloc] init];
+ [menuBar addItem:applicationMenuItem];
+ NSApp.mainMenu = menuBar;
+
+ NSMenu *applicationMenu = [[NSMenu alloc] init];
+ NSString *quitTitle = [@"Quit " stringByAppendingString:applicationName];
+ NSMenuItem *quitItem = [[NSMenuItem alloc] initWithTitle:quitTitle
+ action:@selector(terminate:)
+ keyEquivalent:@"q"];
+ [applicationMenu addItem:quitItem];
+ applicationMenuItem.submenu = applicationMenu;
+}
+
+static NSInteger store_control(NSControl *control)
+{
+ const NSInteger controlId = bridge.nextControlId++;
+ control.tag = controlId;
+ bridge.controls[@(controlId)] = control;
+ return controlId;
+}
+
+void php_macos_app_init(php::Str applicationName)
+{
+ @autoreleasepool {
+ NSApplication *application = NSApplication.sharedApplication;
+ application.activationPolicy = NSApplicationActivationPolicyRegular;
+ bridge = [[TypePHPAppKitBridge alloc] init];
+ install_application_menu(to_ns_string(applicationName));
+ [application finishLaunching];
+ }
+}
+
+void php_macos_create_window(php::Str title, php::Int width, php::Int height)
+{
+ @autoreleasepool {
+ const NSRect frame = NSMakeRect(0, 0, static_cast(width), static_cast(height));
+ const NSWindowStyleMask style = NSWindowStyleMaskTitled |
+ NSWindowStyleMaskClosable |
+ NSWindowStyleMaskMiniaturizable |
+ NSWindowStyleMaskResizable;
+ bridge.window = [[NSWindow alloc] initWithContentRect:frame
+ styleMask:style
+ backing:NSBackingStoreBuffered
+ defer:NO];
+ bridge.window.releasedWhenClosed = NO;
+ bridge.window.delegate = bridge;
+ bridge.window.title = to_ns_string(title);
+ bridge.window.minSize = NSMakeSize(480, 300);
+ [bridge.window center];
+ }
+}
+
+php::Int php_macos_add_label(
+ php::Str text,
+ php::Int x,
+ php::Int y,
+ php::Int width,
+ php::Int height,
+ php::Int fontSize,
+ php::Bool bold)
+{
+ @autoreleasepool {
+ NSTextField *label = [NSTextField wrappingLabelWithString:to_ns_string(text)];
+ label.frame = NSMakeRect(
+ static_cast(x),
+ static_cast(y),
+ static_cast(width),
+ static_cast(height));
+ label.font = bold
+ ? [NSFont systemFontOfSize:static_cast(fontSize)
+ weight:NSFontWeightSemibold]
+ : [NSFont systemFontOfSize:static_cast(fontSize)];
+ label.alignment = NSTextAlignmentCenter;
+ label.autoresizingMask = NSViewWidthSizable | NSViewMinYMargin;
+ [bridge.window.contentView addSubview:label];
+ return static_cast(store_control(label));
+ }
+}
+
+php::Int php_macos_add_button(
+ php::Str title,
+ php::Int x,
+ php::Int y,
+ php::Int width,
+ php::Int height)
+{
+ @autoreleasepool {
+ NSButton *button = [NSButton buttonWithTitle:to_ns_string(title)
+ target:bridge
+ action:@selector(controlActivated:)];
+ button.frame = NSMakeRect(
+ static_cast(x),
+ static_cast(y),
+ static_cast(width),
+ static_cast(height));
+ button.bezelStyle = NSBezelStyleRounded;
+ button.keyEquivalent = @"\r";
+ button.autoresizingMask = NSViewMinXMargin | NSViewMaxXMargin | NSViewMinYMargin;
+ [bridge.window.contentView addSubview:button];
+ return static_cast(store_control(button));
+ }
+}
+
+void php_macos_set_control_text(php::Int controlId, php::Str text)
+{
+ @autoreleasepool {
+ NSControl *control = bridge.controls[@(static_cast(controlId))];
+ if (control != nil) {
+ control.stringValue = to_ns_string(text);
+ }
+ }
+}
+
+void php_macos_show_window()
+{
+ @autoreleasepool {
+ [bridge.window makeKeyAndOrderFront:nil];
+ bridge.running = YES;
+ [NSApp activateIgnoringOtherApps:YES];
+ }
+}
+
+php::Int php_macos_next_event()
+{
+ while (bridge.running) {
+ @autoreleasepool {
+ NSEvent *event = [NSApp nextEventMatchingMask:NSEventMaskAny
+ untilDate:NSDate.distantFuture
+ inMode:NSDefaultRunLoopMode
+ dequeue:YES];
+ if (event != nil) {
+ [NSApp sendEvent:event];
+ [NSApp updateWindows];
+ }
+
+ if (bridge.pendingControlId != 0) {
+ const NSInteger controlId = bridge.pendingControlId;
+ bridge.pendingControlId = 0;
+ return static_cast(controlId);
+ }
+ }
+ }
+ return -1;
+}
diff --git a/examples/objective-c-macos/objc-src/macos_bridge.stub.php b/examples/objective-c-macos/objc-src/macos_bridge.stub.php
new file mode 100644
index 00000000..10224237
--- /dev/null
+++ b/examples/objective-c-macos/objc-src/macos_bridge.stub.php
@@ -0,0 +1,25 @@
+&2
+ exit 1
+fi
+
+mkdir -p "$bundle/Contents/MacOS"
+cp "$project_dir/Info.plist" "$bundle/Contents/Info.plist"
+cp "$executable" "$bundle/Contents/MacOS/typephp-macos-hello"
+codesign --force --deep --sign - "$bundle"
+
+echo "Created $bundle"
diff --git a/examples/objective-c-macos/php-src/main.php b/examples/objective-c-macos/php-src/main.php
new file mode 100644
index 00000000..cd196ff7
--- /dev/null
+++ b/examples/objective-c-macos/php-src/main.php
@@ -0,0 +1,38 @@
+