app: [iOS] add support for buildmode exe

Up until now, the iOS part has relied on a tool such as gogio to
synthesize a main function. This change adds support for running direcetly
in exe mode, while retaining support for embedded Gio in C programs.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
This commit is contained in:
Elias Naur
2024-06-02 11:22:31 +02:00
parent 175e134478
commit e6da07a85a
2 changed files with 58 additions and 1 deletions
+38 -1
View File
@@ -12,6 +12,7 @@ package app
#include <UIKit/UIKit.h> #include <UIKit/UIKit.h>
#include <stdint.h> #include <stdint.h>
__attribute__ ((visibility ("hidden"))) int gio_applicationMain(int argc, char *argv[]);
__attribute__ ((visibility ("hidden"))) void gio_viewSetHandle(CFTypeRef viewRef, uintptr_t handle); __attribute__ ((visibility ("hidden"))) void gio_viewSetHandle(CFTypeRef viewRef, uintptr_t handle);
struct drawParams { struct drawParams {
@@ -81,6 +82,7 @@ import "C"
import ( import (
"image" "image"
"io" "io"
"os"
"runtime" "runtime"
"runtime/cgo" "runtime/cgo"
"runtime/debug" "runtime/debug"
@@ -394,12 +396,47 @@ func newWindow(win *callbacks, options []Option) {
<-mainWindow.windows <-mainWindow.windows
} }
var mainMode = mainModeUndefined
const (
mainModeUndefined = iota
mainModeExe
mainModeLibrary
)
func osMain() { func osMain() {
if !isMainThread() {
panic("app.Main must be run on the main goroutine")
}
switch mainMode {
case mainModeUndefined:
mainMode = mainModeExe
var argv []*C.char
for _, arg := range os.Args {
a := C.CString(arg)
defer C.free(unsafe.Pointer(a))
argv = append(argv, a)
}
C.gio_applicationMain(C.int(len(argv)), unsafe.SliceData(argv))
case mainModeExe:
panic("app.Main may be called only once")
case mainModeLibrary:
// Do nothing, we're embedded as a library.
}
} }
//export gio_runMain //export gio_runMain
func gio_runMain() { func gio_runMain() {
runMain() if !isMainThread() {
panic("app.Main must be run on the main goroutine")
}
switch mainMode {
case mainModeUndefined:
mainMode = mainModeLibrary
runMain()
case mainModeExe:
// Do nothing, main has already been called.
}
} }
func (UIKitViewEvent) implementsViewEvent() {} func (UIKitViewEvent) implementsViewEvent() {}
+20
View File
@@ -280,3 +280,23 @@ void gio_viewSetHandle(CFTypeRef viewRef, uintptr_t handle) {
GioView *v = (__bridge GioView *)viewRef; GioView *v = (__bridge GioView *)viewRef;
v.handle = handle; v.handle = handle;
} }
@interface _gioAppDelegate : UIResponder <UIApplicationDelegate>
@property (strong, nonatomic) UIWindow *window;
@end
@implementation _gioAppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
GioViewController *controller = [[GioViewController alloc] initWithNibName:nil bundle:nil];
self.window.rootViewController = controller;
[self.window makeKeyAndVisible];
return YES;
}
@end
int gio_applicationMain(int argc, char *argv[]) {
@autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([_gioAppDelegate class]));
}
}