Documentation
¶
Overview ¶
Package objc is a pure-Go (CGO_ENABLED=0) bridge to the macOS Objective-C runtime. It reaches the OS entirely through github.com/ebitengine/purego — dlopen + objc_msgSend — so it links with no cgo and no shelling out to osascript.
It exists to end the copy-paste of the same Objective-C plumbing across the fleet's CGO=0 macOS code (go-macos/notify, go-widgets/tray, the go-news-reader and go-reddit readers, …): every one of them independently re-implemented selector/class lookup, NSString<->Go bridging, framework dlopen, autorelease-pool handling and a run loop. This package is the single shared home for those primitives.
Surface ¶
- Sel / GetClass / ClassID: cached selector and class lookup.
- ID.Send and the generic Send: typed objc_msgSend helpers (the generic form carries float64/CGFloat and struct returns through the correct calling convention).
- RegisterClass: define an Objective-C class at runtime from Go method closures.
- NSString / GoString: NSString<->Go string conversion. GoString copies via -getCString:maxLength:encoding: (never a raw -UTF8String pointer deref, which trips go vet's unsafeptr check).
- Stringify / DictToMap / MapToDict: NSObject/NSDictionary helpers.
- Load plus the framework-path constants (Foundation, AppKit, WebKit, CoreFoundation, LibSystem): idempotent dlopen.
- AutoreleasePool: run a closure inside an NSAutoreleasePool scope.
- App / RunApp: the shared NSApplication and its [NSApp run] loop.
- Run: a Foundation run-loop runner pinned to a locked OS thread, with a task queue serviced on that thread — for observer-driven Foundation work (e.g. NSDistributedNotificationCenter).
Portability ¶
Every exported symbol is defined on all platforms so consumers cross-compile. On non-darwin GOOS the runtime entry points report ErrUnsupported (or return a zero ID); the OS-independent logic — the selector/class caches, name validation and the string-marshalling core — stays fully functional and testable there.
Index ¶
- Constants
- Variables
- func AutoreleasePool(fn func())
- func DictToMap(dict ID) map[string]string
- func GoString(id ID) string
- func Load(paths ...string) error
- func Run(ctx context.Context, runnerClass Class, setup func(r *Runner)) error
- func RunApp(policy int)
- func Send[T any](id ID, sel SEL, args ...any) T
- func Stringify(v ID) string
- func ValidateName(name string) error
- type Class
- type ID
- type IMP
- type MethodDef
- type Protocol
- type Runner
- type SEL
Constants ¶
const ( Foundation = "/System/Library/Frameworks/Foundation.framework/Foundation" AppKit = "/System/Library/Frameworks/AppKit.framework/AppKit" WebKit = "/System/Library/Frameworks/WebKit.framework/WebKit" CoreFoundation = "/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation" Security = "/System/Library/Frameworks/Security.framework/Security" LibSystem = "/usr/lib/libSystem.B.dylib" )
Standard framework and dylib paths for Load.
Variables ¶
var ( // ErrUnsupported is returned by the runtime entry points on non-darwin // platforms (the whole runtime is macOS-only). ErrUnsupported = errors.New("objc: unsupported on this platform (darwin only)") // ErrEmptyName is returned when a selector or class name is empty. ErrEmptyName = errors.New("objc: empty name") // ErrNameHasNUL is returned when a selector or class name contains a NUL // byte (the C runtime terminates names at the first NUL, so an embedded one // would silently truncate). ErrNameHasNUL = errors.New("objc: name contains NUL byte") // ErrDlopen wraps a framework dlopen failure from [Load]. ErrDlopen = errors.New("objc: dlopen failed") )
Errors reported by the package. They are stable and may be tested with errors.Is.
Functions ¶
func AutoreleasePool ¶
func AutoreleasePool(fn func())
AutoreleasePool runs fn directly on non-darwin platforms (there is no pool to establish), so callers can wrap code unconditionally.
func GoString ¶
GoString copies an NSString's UTF-8 bytes into a Go-owned buffer and returns them. It returns "" for the nil object or an empty string. It fills a Go slice via -getCString:maxLength:encoding: rather than dereferencing the ObjC-owned -UTF8String pointer, so it stays free of any uintptr->Pointer arithmetic (the buffer handed to ObjC is a live Go pointer the collector tracks).
func Load ¶
Load dlopens each of paths (idempotently — dlopen refcounts, and a repeat open of an already-resident framework is cheap). It returns the first failure wrapped in ErrDlopen. Use the framework-path constants, e.g. Load(Foundation, AppKit).
func Run ¶
Run reports ErrUnsupported on non-darwin platforms.
func ValidateName ¶
ValidateName rejects names the C runtime cannot carry: empty (ErrEmptyName) or containing a NUL byte (ErrNameHasNUL, since objc_registerName / objc_getClass terminate at the first NUL and would silently truncate). It is a convenience for consumers that build selector or class names from untrusted input before passing them to Sel, GetClass or RegisterClass.
Types ¶
type Class ¶
type Class uintptr
Class is an Objective-C class object.
func GetClass ¶
GetClass returns the class named name, caching the result. An unknown class (or the zero name) yields the zero class.
func RegisterClass ¶
RegisterClass reports ErrUnsupported on non-darwin platforms.
func RegisterClassWithProtocols ¶ added in v0.1.1
func RegisterClassWithProtocols(name string, super Class, protocols []*Protocol, methods []MethodDef) (Class, error)
RegisterClassWithProtocols reports ErrUnsupported on non-darwin platforms.
type ID ¶
type ID uintptr
ID is an Objective-C object pointer; the zero value is nil.
func ClassID ¶
ClassID returns the class named name as an ID, so class ("factory") messages (alloc, sharedApplication, …) can be sent to it directly.
type MethodDef ¶
MethodDef binds a selector to a Go closure for RegisterClass. On darwin this is an alias of purego's objc.MethodDef; here it is the equivalent shape.
type Protocol ¶ added in v0.1.1
type Protocol struct{}
Protocol is an Objective-C protocol. On darwin it is an alias of purego's objc.Protocol; here it is a placeholder so the signatures compile.
func GetProtocol ¶ added in v0.1.1
GetProtocol reports a nil protocol on non-darwin platforms.
type Runner ¶
type Runner struct {
// contains filtered or unexported fields
}
Runner is the non-darwin stand-in for the Run handle. Its methods are no-ops (Submit runs fn directly) so consumer code that references them still compiles.