golang开发原生macOS应用程序插件库DarwinKit的使用

Golang开发原生macOS应用程序插件库DarwinKit的使用

DarwinKit Logo

重要通知

2024年7月11日:MacDriver现已更名为DarwinKit!作为项目赞助者,您现在可以获得高质量的示例启动应用程序。

简介

DarwinKit让您能够使用Go语言与支持的Apple框架交互,并构建原生应用程序。安装XCode和Go 1.18+后,您可以在main.go文件中编写以下程序:

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() {
	// 运行macOS应用程序事件循环,成功时调用回调
	macos.RunApp(func(app appkit.Application, delegate *appkit.ApplicationDelegate) {
		app.SetActivationPolicy(appkit.ApplicationActivationPolicyRegular)
		app.ActivateIgnoringOtherApps(true)

		url := foundation.URL_URLWithString("https://github.com/sponsors/darwinkitdev")
		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
		})
	})
}

然后在该目录中运行:

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

第一次运行可能需要一些时间,但窗口弹出后,您就成功创建了一个不使用XCode或Objective-C的macOS程序。运行go build可获取可执行文件。

示例演示

以下是使用DarwinKit构建的一些示例应用:

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

注意事项

  1. 您仍然需要了解或学习Apple框架的工作原理,因此必须使用Apple文档并理解如何将Objective-C示例代码转换为等效的Go与DarwinKit代码。

  2. 您的程序使用cgo链接实际的Apple框架,因此需要安装XCode以获取框架头文件。

  3. 您将使用两个内存管理系统。框架对象由Objective-C内存管理管理,因此请务必阅读我们关于DarwinKit内存管理的文档。

  4. 框架中的异常会导致段错误,给您提供Objective-C堆栈跟踪和Go panic堆栈跟踪。您将调试一个混合的Go和Objective-C程序。

  5. 与GUI对象交互的Goroutine需要在主线程上调度操作,否则会导致段错误。

对于简单程序来说,这些都是可以处理的,但这些是我们不建议使用DarwinKit构建大型/复杂程序的原因。

工作原理

DarwinKit的核心是一个使用cgo和libffi包装Objective-C运行时的包。这实际上是您与Objective-C对象和类交互所需的全部内容。

这些绑定很好,但我们需要为我们想要使用的每个API定义它们。目前,Apple有大约200个框架,近5000个类,共有77k个方法和属性。更不用说我们需要与这些对象一起使用的所有常量、函数、结构体、联合体和枚举。

因此,DarwinKit生成其绑定。这是困难的部分。确保生成管道准确地为所有可能的符号生成可用的绑定是一个相当艰巨、迭代、手动过程。然后,由于我们将生活在单个命名空间中的符号移动到Go包中,我们必须手动解耦它们之间的依赖关系,以避免循环导入。

感谢

该项目受到并最初基于Mikkel Krautz编写的包。最新版本基于Dong Liu编写的包。

声明

该项目不与Apple关联或受Apple支持。

许可证

MIT


更多关于golang开发原生macOS应用程序插件库DarwinKit的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于golang开发原生macOS应用程序插件库DarwinKit的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


DarwinKit - Go语言开发macOS原生应用的利器

DarwinKit是一个用Go语言编写的库,专门用于开发macOS原生应用程序和插件。它提供了与macOS Darwin系统底层API交互的能力,让Go开发者可以构建真正的原生macOS应用。

主要特性

  1. 原生Cocoa/AppKit集成
  2. Objective-C运行时交互
  3. 完整的macOS API访问
  4. 插件系统支持
  5. 简洁的Go API设计

安装

go get github.com/progrium/macdriver/darwin

基本使用示例

创建简单窗口应用

package main

import (
	"github.com/progrium/macdriver/cocoa"
	"github.com/progrium/macdriver/objc"
)

func main() {
	app := cocoa.NSApp_WithDidLaunch(func(notification objc.Object) {
		window := cocoa.NSWindow_Init(
			cocoa.Rect(0, 0, 600, 400),
			cocoa.NSWindowStyleMaskTitled|
				cocoa.NSWindowStyleMaskClosable|
				cocoa.NSWindowStyleMaskMiniaturizable,
			cocoa.NSWindowBackingStoreBuffered,
			false,
		)
		window.SetTitle("Go macOS App")
		window.MakeKeyAndOrderFront(nil)
	})
	app.Run()
}

创建菜单栏应用

package main

import (
	"github.com/progrium/macdriver/cocoa"
	"github.com/progrium/macdriver/objc"
)

func main() {
	app := cocoa.NSApp_WithDidLaunch(func(notification objc.Object) {
		statusItem := cocoa.NSStatusBar_System().StatusItemWithLength(cocoa.NSVariableStatusItemLength)
		statusItem.Button().SetTitle("Go Menu")

		menu := cocoa.NSMenu_New()
		item := cocoa.NSMenuItem_New()
		item.SetTitle("Quit")
		item.SetAction(objc.Sel("terminate:"))
		menu.AddItem(item)
		statusItem.SetMenu(menu)
	})
	app.Run()
}

高级功能

与Objective-C交互

import "github.com/progrium/macdriver/objc"

// 调用Objective-C方法
str := objc.NewNSString("Hello from Go")
length := str.Send("length").Int()
fmt.Println("String length:", length)

创建自定义视图

type CustomView struct {
	cocoa.NSView
}

func NewCustomView(frame cocoa.Rect) *CustomView {
	view := &CustomView{}
	view.NSView = cocoa.NSView_Init(frame)
	view.SetWantsLayer(true)
	view.Layer().SetBackgroundColor(cocoa.NSColor_Red().CGColor())
	return view
}

// 使用自定义视图
window.SetContentView(NewCustomView(cocoa.Rect(0, 0, 300, 200)))

开发系统插件

package main

import (
	"github.com/progrium/macdriver/cocoa"
	"github.com/progrium/macdriver/objc"
)

//export PluginEntry
func PluginEntry() {
	app := cocoa.NSApp_WithDidLaunch(func(notification objc.Object) {
		alert := cocoa.NSAlert_New()
		alert.SetMessageText("Plugin Loaded")
		alert.SetInformativeText("This plugin was written in Go!")
		alert.RunModal()
	})
	app.Run()
}

性能考虑

  1. Go与Objective-C桥接会有一定性能开销
  2. 频繁调用的核心逻辑建议用C实现
  3. 大量UI更新应在主线程执行

调试技巧

  1. 使用NSLog输出调试信息
  2. 启用Xcode调试器附加到进程
  3. 检查控制台日志中的Objective-C异常

替代方案比较

  1. Electron: 跨平台但资源占用高
  2. SwiftUI: 原生但需要学习Swift
  3. DarwinKit: Go语言优势,接近原生性能

DarwinKit为Go开发者打开了macOS原生开发的大门,特别适合已有Go代码库需要macOS原生界面,或者希望用Go编写系统插件的场景。

回到顶部