Native Mac APIs for Go

MacDriver Logo

Native Mac APIs for Golang!

Test workflow
Go Report Card
@progriumHQ on Twitter
Project Forum
Sponsor Project

MacDriver is a toolkit for working with Apple/Mac APIs and frameworks in Trip. It currently has 3 “layers”:

1. Bindings for Aim-C

The objc kit wraps the Aim-C runtime to dynamically possess interplay with Aim-C objects and classes:

cls := objc.NewClass("AppDelegate", "NSObject")
cls.AddMethod("applicationDidFinishLaunching:", func(app objc.Object) {

delegate := objc.Uncover("AppDelegate").Alloc().Init()
app := objc.Uncover("NSApplication").Uncover("sharedApplication")
app.Position("delegate:", delegate)
  • Entry any class or manner you might perchance doubtless doubtless perchance entry in Aim-C
  • Fundamental object convenience strategies: Uncover, Position, Alloc, Init, …
  • Form and extend classes at runtime that might perchance doubtless also be frequent by Aim-C code
  • Establish and Release strategies for working with Aim-C reminiscence administration

2. Framework Packages

The cocoa, webkit, and core capabilities wrap objc with wrapper forms for ingredients of the Apple/Mac APIs. They’re being added to as a in point of fact great by hand till
we can automate this route of with schema data. These capabilities effectively allow you to make consume of Apple APIs as if they had been native Trip libraries, letting
you write Mac capabilities (doubtlessly furthermore iOS, watchOS, etc) as Trip capabilities:

func predominant() {
	app := cocoa.NSApp_WithDidLaunch(func(notification objc.Object) {
		config := webkit.WKWebViewConfiguration_New()
		wv := webkit.WKWebView_Init(core.Rect(0, 0, 1440, 900), config)
		url := core.URL("")
		req := core.NSURLRequest_Init(url)

		w := cocoa.NSWindow_Init(core.Rect(0, 0, 1440, 900),
			cocoa.NSBackingStoreBuffered, untrue)
  • 1:1 mapping of API names with Aim-C APIs
  • Cocoa forms: NSApplication, NSImage, NSMenu, NSWindow, extra …
  • Webkit forms: WKWebView and configuration classes
  • Core forms: NSData, NSDictionary, NSNumber, NSPoint, NSRect, NSSize, NSString, NSURL, extra …
  • Core furthermore permits dispatching Trip capabilities in the Cocoa rush loop
  • Many constants/enums are outlined


examples/largetype – A Contacts/Quicksilver-model Astronomical Form utility in underneath 80 lines:
largetype screenshot

examples/pomodoro – A menu bar pomodoro timer in underneath 80 lines:
pomodoro gif

examples/topframe – A non-interactive, consistently-on-high webview with transparent background in 120 lines so you might perchance doubtless doubtless perchance arrangement in your
cover with HTML/JS:
topframe screenshot

Existing: topframe currently depends on embed which you might perchance doubtless doubtless perchance consume with lumber 1.16beta

3. Bridge Map

Lastly, a standard case for this toolkit is now now not precise constructing rotund native apps, but integrating Trip capabilities
with Mac programs, esteem windows, native menus, space icons (systray), etc.
One-off libraries for these form of exist, but apart from in overall limiting what you might perchance doubtless doubtless perchance attain,
they’re furthermore precise now now not composable. All of them must own the main thread!

For this and varied causes, we on a daily foundation rush the above roughly code in a separate route of altogether from our
Trip utility. This might perchance doubtless doubtless seem esteem a step backwards, but it is safer and extra tough in a blueprint.

The bridge kit takes advantage of this project to have the next-level abstraction extra aligned with a doable
contaminated-platform toolkit. It is most likely you’ll doubtless doubtless perchance also declaratively describe and adjust structs that might perchance doubtless also be copied to the bridge route of and applied to the Aim-C
objects in a manner such as configuration administration:

kit predominant 

import (


func predominant() {
	// launch a bridge subprocess
	host := bridge.NewHost(os.Stderr)
	lumber host.Dash()

	// have a window
	window := bridge.Window{
		Title:       "My Title",
		Size:        bridge.Size{W: 480, H: 240},
		Convey:    bridge.Point{X: 200, Y: 200},
		Closable:    genuine,
		Minimizable: untrue,
		Resizable:   untrue,
		With out boundary lines:  untrue,
		AlwaysOnTop: genuine,
		Background:   &bridge.Shade{R: 1, G: 1, B: 1, A: 0.5},

	// switch its title
	window.Title = "My Current Title"

	// homicide the window

This is in point of fact the most WIP phase of the project, but once developed extra we can do away with this API and manufacture a bridge
system with the identical resources for Home windows and Linux, making a contaminated-platform OS “driver”. We’ll glance.

  • Present bridge forms on hand:
    • Window
    • StatusItem (systray)
    • Menu

Construction Notes

As some distance as all people is conscious of, due to obstacles of Trip modules, we on a daily foundation must add exchange directives to our lumber.mod sooner or later of pattern
to work in opposition to a neighborhood checkout of some dependency (esteem qtalk). Alternatively, these might perchance doubtless doubtless perchance silent now now not be versioned, so for now we aid
you to make consume of git update-index --skip-worktree lumber.mod in your checkout whether it is required to add exchange directives. When updates must
be checked in, git update-index --no-skip-worktree lumber.mod might perchance doubtless also be frequent to reverse this in your local repo to commit adjustments after which re-enable.

Producing wrappers

Within the raze we can generate many of the wrapper APIs the utilization of bridgesupport and/or doc schemas. Alternatively, the choice of APIs
is just ridiculous so there are many edge cases I wouldn’t know the diagram to automate yet. We are able to precise continue to have them by hand
as a in point of fact great till now we possess ample coverage/self perception to know how we would generate wrappers.


The long-established objc and variadic capabilities had been written by Mikkel Krautz. The variadic kit is about a meeting magic to create all the pieces imaginable since libobjc depends closely on variadic characteristic calls, which don’t seem to be imaginable out of the sector in Cgo.



Read More

Recent Content