darwinkit

module
v0.5.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 21, 2024 License: MIT

README

DarwinKit Logo

Native Apple APIs for Golang!

GoDoc Go Report Card Project Forum Sponsor Project

[!IMPORTANT] June 13, 2024: MacDriver is now DarwinKit and we're about to release 0.5.0! The legacy branch and previous releases are still available for existing code to work against. Use main until 0.5.0 is released.


ScanDrop Demo SnowScape Demo MenuSpacer Demo ClipTrail Demo

DarwinKit lets you work with supported Apple frameworks and build native applications using Go. With XCode and Go 1.18+ installed, you can write this program in a main.go file:

package main

import (
	"github.com/progrium/darwinkit/objc"
	"github.com/progrium/darwinkit/macos"
	"github.com/progrium/darwinkit/macos/appkit"
	"github.com/progrium/darwinkit/macos/foundation"
	"github.com/progrium/darwinkit/macos/webkit"
)

func main() {
	// runs macOS application event loop with a callback on success
	macos.RunApp(func(app appkit.Application, delegate *appkit.ApplicationDelegate) {
		app.SetActivationPolicy(appkit.ApplicationActivationPolicyRegular)
		app.ActivateIgnoringOtherApps(true)

		url := foundation.URL_URLWithString("http://progrium.com")
		req := foundation.NewURLRequestWithURL(url)
		frame := foundation.Rect{Size: foundation.Size{1440, 900}}

		config := webkit.NewWebViewConfiguration()
		wv := webkit.NewWebViewWithFrameConfiguration(frame, config)
		wv.LoadRequest(req)

		w := appkit.NewWindowWithContentRectStyleMaskBackingDefer(frame,
			appkit.ClosableWindowMask|appkit.TitledWindowMask,
			appkit.BackingStoreBuffered, false)
		objc.Retain(&w)
		w.SetContentView(wv)
		w.MakeKeyAndOrderFront(w)
		w.Center()

		delegate.SetApplicationShouldTerminateAfterLastWindowClosed(func(appkit.Application) bool {
			return true
		})
	})
}

Then in this directory run:

go mod init helloworld
go get github.com/progrium/darwinkit@main
go run main.go

This may take a moment the first time, but once the window pops up you just made a macOS program without using XCode or Objective-C. Run go build to get an executable.

Although currently outside the scope of this project, if you wanted you could put this executable into an Application bundle. You could even add entitlements, then sign and notarize this bundle or executable to let others run it. It could theoretically even be put on the App Store. It could theoretically be put on an iOS, tvOS, or watchOS device, though you would have to use different platform specific frameworks.

Caveats

  • You still need to know or learn how Apple frameworks work, so you'll have to use Apple documentation and understand how to translate Objective-C example code to the equivalent Go with DarwinKit.
  • Your programs link against the actual Apple frameworks using cgo, so XCode needs to be installed for the framework headers.
  • You will be using two memory management systems. Framework objects are managed by Objective-C memory management, so be sure to read our docs on memory management with DarwinKit.
  • Exceptions in frameworks will segfault, giving you both an Objective-C stacktrace and a Go panic stacktrace. You will be debugging a hybrid Go and Objective-C program.
  • Goroutines that interact with GUI objects need to dispatch operations on the main thread otherwise it will segfault.

This is all tenable for simple programs, but these are the reasons we don't recommend large/complex programs using DarwinKit.

Examples

There are basic usage examples here in this repo, but there are higher-quality full utilities you can use as examples or starter templates when you sponsor.

LargeType Demo ScanDrop Demo SnowScape Demo LiveTemp Demo MenuSpacer Demo ClipTrail Demo FocusTimer Demo

How it works

Brief background on Objective-C

Ever since acquiring NeXT Computer in the 90s, Apple has used NeXTSTEP as the basis of their software stack, which is written in Objective-C. Unlike most systems languages with object orientation, Objective-C implements OOP as a runtime library. In fact, Objective-C is just C with the weird OOP specific syntax rewritten into C calls to libobjc, which is a normal C library implementing an object runtime. This runtime could be used to bring OOP to any language that can make calls to C code. It also lets you interact with objects and classes registered by other libraries, such as the Apple frameworks.

At the heart of DarwinKit is a package wrapping the Objective-C runtime using cgo and libffi. This is actually all you need to interact with Objective-C objects and classes, it'll just look like this:

app := objc.Call[objc.Object](objc.GetClass("NSApplication"), objc.Sel("sharedApplication"))
objc.Call[objc.Void](app, objc.Sel("run"))

So we wrap these calls in a Go API that lets us write code like this:

app := appkit.Application_SharedApplication()
app.Run()

These bindings are great, but we need to define them for every API we want to use. Presently, Apple has around 200 frameworks of nearly 5000 classes with 77k combined methods and properties. Not to mention all the constants, functions, structs, unions, and enums we need to work with those objects.

So DarwinKit generates its bindings. This is the hard part. Making sure the generation pipeline accurately produces usable bindings for all possible symbols is quite an arduous, iterative, manual process. Then since we're moving symbols that lived in a single namespace into Go packages, we have to manually decouple dependencies between them enough to avoid circular imports. If you want to help add frameworks, read our documentation on generation.

Objects are passed around as typed pointer values in Objective-C. When we receive an object from a method call in Go, the objc package receives it as a raw pointer, which it first puts into an unsafe.Pointer. The bindings for a class define a struct type that embeds an objc.Object struct, which contains a single field to hold the unsafe.Pointer. So unless working with a primitive type, you're working with an unsafe.Pointer wrapped in an objc.Object wrapped in a struct type that has the methods for the class of the object of the pointer. Be sure to read our documentation on memory management.

If you have questions, feel free to ask in the discussion forums.

Thanks

This project was inspired by and originally based on packages written by Mikkel Krautz. The latest version is based on packages written by Dong Liu.

Notice

This project is not affiliated or supported by Apple.

License

MIT

Directories

Path Synopsis
Execute code concurrently on multicore hardware by submitting work to dispatch queues managed by the system.
Execute code concurrently on multicore hardware by submitting work to dispatch queues managed by the system.
helper
internal
set
macOS Frameworks
macOS Frameworks
WIP
WIP
WIP
WIP
WIP
WIP
WIP
WIP
WIP
appkit
Construct and manage a graphical, event-driven user interface for your macOS app.
Construct and manage a graphical, event-driven user interface for your macOS app.
avfoundation
Work with audiovisual assets, control device cameras, process audio, and configure system audio interactions.
Work with audiovisual assets, control device cameras, process audio, and configure system audio interactions.
avkit
Create user interfaces for media playback, complete with transport controls, chapter navigation, picture-in-picture support, and display of subtitles and closed captions.
Create user interfaces for media playback, complete with transport controls, chapter navigation, picture-in-picture support, and display of subtitles and closed captions.
cloudkit
Store structured app and user data in iCloud containers that all users of your app can share.
Store structured app and user data in iCloud containers that all users of your app can share.
contacts
Access the user's contacts, and format and localize contact information.
Access the user's contacts, and format and localize contact information.
contactsui
Display information about users’ contacts in a graphical interface.
Display information about users’ contacts in a graphical interface.
coreaudio
Use the Core Audio framework to interact with device’s audio hardware.
Use the Core Audio framework to interact with device’s audio hardware.
coreaudiotypes
Use specialized data types to interact with audio streams, complex buffers, and audiovisual timestamps.
Use specialized data types to interact with audio streams, complex buffers, and audiovisual timestamps.
coredata
Persist or cache data on a single device, or sync data to multiple devices with CloudKit.
Persist or cache data on a single device, or sync data to multiple devices with CloudKit.
corefoundation
Access low-level functions, primitive data types, and various collection types that are bridged seamlessly with the Foundation framework.
Access low-level functions, primitive data types, and various collection types that are bridged seamlessly with the Foundation framework.
coregraphics
Harness the power of Quartz technology to perform lightweight 2D rendering with high-fidelity output.
Harness the power of Quartz technology to perform lightweight 2D rendering with high-fidelity output.
coreimage
Use built-in or custom filters to process still and video images.
Use built-in or custom filters to process still and video images.
corelocation
Obtain the geographic location and orientation of a device.
Obtain the geographic location and orientation of a device.
coremedia
Represent time-based audio-visual assets with essential data types.
Represent time-based audio-visual assets with essential data types.
coremediaio
Securely support custom camera devices in macOS.
Securely support custom camera devices in macOS.
coremidi
Communicate with MIDI devices such as hardware keyboards and synthesizers.
Communicate with MIDI devices such as hardware keyboards and synthesizers.
coreml
Integrate machine learning models into your app.
Integrate machine learning models into your app.
corespotlight
Index your app so users can search the content from Spotlight and Safari.
Index your app so users can search the content from Spotlight and Safari.
corevideo
Process digital video, including manipulation of individual frames, using a pipeline-based API and support for both Metal and OpenGL.
Process digital video, including manipulation of individual frames, using a pipeline-based API and support for both Metal and OpenGL.
fileprovider
An extension other apps use to access files and folders managed by your app and synced with a remote storage.
An extension other apps use to access files and folders managed by your app and synced with a remote storage.
foundation
Access essential data types, collections, and operating-system services to define the base layer of functionality for your app.
Access essential data types, collections, and operating-system services to define the base layer of functionality for your app.
imageio
Read and write most image file formats, and access an image’s metadata.
Read and write most image file formats, and access an image’s metadata.
iosurface
Share hardware-accelerated buffer data (framebuffers and textures) across multiple processes.
Share hardware-accelerated buffer data (framebuffers and textures) across multiple processes.
mediaplayer
Find and play songs, audio podcasts, audio books, and more from within your app.
Find and play songs, audio podcasts, audio books, and more from within your app.
metal
Render advanced 3D graphics and compute data in parallel with graphics processors.
Render advanced 3D graphics and compute data in parallel with graphics processors.
mps
Optimize graphics and compute performance with kernels that are fine-tuned for the unique characteristics of each Metal GPU family.
Optimize graphics and compute performance with kernels that are fine-tuned for the unique characteristics of each Metal GPU family.
mpsgraph
Build, compile, and execute customized multidimensional compute graphs for linear algebra, machine learning, computer vision, and other similar domains.
Build, compile, and execute customized multidimensional compute graphs for linear algebra, machine learning, computer vision, and other similar domains.
quartz
Allow users to browse, edit, and save images, using slideshows and Core Image filters.
Allow users to browse, edit, and save images, using slideshows and Core Image filters.
quartzcore
Render, compose, and animate visual elements.
Render, compose, and animate visual elements.
sysconfig
Allow applications to access a device’s network configuration settings.
Allow applications to access a device’s network configuration settings.
uti
Provide uniform type identifiers that describe file types for storage or transfer.
Provide uniform type identifiers that describe file types for storage or transfer.
vision
Apply computer vision algorithms to perform a variety of tasks on input images and video.
Apply computer vision algorithms to perform a variety of tasks on input images and video.
webkit
Integrate web content seamlessly into your app, and customize content interactions to meet your app’s needs.
Integrate web content seamlessly into your app, and customize content interactions to meet your app’s needs.
Gain low-level access to the Objective-C runtime and the Objective-C root types.
Gain low-level access to the Objective-C runtime and the Objective-C root types.
ffi

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL