v0.8.0-alpha.2 bcc8fd4

objc_runtime_darwin_test.go RawHistoryFolder

1// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
3
4package objc_test
5
6import (
7	"fmt"
8	"reflect"
9	"testing"
10
11	"github.com/ebitengine/purego"
12	"github.com/ebitengine/purego/objc"
13)
14
15func ExampleRegisterClass_helloworld() {
16	class, err := objc.RegisterClass(
17		"FooObject",
18		objc.GetClass("NSObject"),
19		nil,
20		nil,
21		[]objc.MethodDef{
22			{
23				Cmd: objc.RegisterName("run"),
24				Fn: func(self objc.ID, _cmd objc.SEL) {
25					fmt.Println("Hello World!")
26				},
27			},
28		},
29	)
30	if err != nil {
31		panic(err)
32	}
33
34	object := objc.ID(class).Send(objc.RegisterName("new"))
35	object.Send(objc.RegisterName("run"))
36	// Output: Hello World!
37}
38
39func ExampleRegisterClass() {
40	var (
41		sel_new    = objc.RegisterName("new")
42		sel_init   = objc.RegisterName("init")
43		sel_setBar = objc.RegisterName("setBar:")
44		sel_bar    = objc.RegisterName("bar")
45
46		BarInit = func(id objc.ID, cmd objc.SEL) objc.ID {
47			return id.SendSuper(cmd)
48		}
49	)
50
51	class, err := objc.RegisterClass(
52		"BarObject",
53		objc.GetClass("NSObject"),
54		[]*objc.Protocol{
55			objc.GetProtocol("NSDelegateWindow"),
56		},
57		[]objc.FieldDef{
58			{
59				Name:      "bar",
60				Type:      reflect.TypeOf(int(0)),
61				Attribute: objc.ReadWrite,
62			},
63			{
64				Name:      "foo",
65				Type:      reflect.TypeOf(false),
66				Attribute: objc.ReadWrite,
67			},
68		},
69		[]objc.MethodDef{
70			{
71				Cmd: sel_init,
72				Fn:  BarInit,
73			},
74		},
75	)
76	if err != nil {
77		panic(err)
78	}
79
80	object := objc.ID(class).Send(sel_new)
81	object.Send(sel_setBar, 123)
82	bar := int(object.Send(sel_bar))
83	fmt.Println(bar)
84	// Output: 123
85}
86
87func ExampleIMP() {
88	imp := objc.NewIMP(func(self objc.ID, _cmd objc.SEL, a3, a4, a5, a6, a7, a8, a9 int) {
89		fmt.Println("IMP:", self, _cmd, a3, a4, a5, a6, a7, a8, a9)
90	})
91
92	purego.SyscallN(uintptr(imp), 105, 567, 9, 2, 3, ^uintptr(4), 4, 8, 9)
93	// Output: IMP: 105 567 9 2 3 -5 4 8 9
94}
95
96func ExampleID_SendSuper() {
97	super, err := objc.RegisterClass(
98		"SuperObject",
99		objc.GetClass("NSObject"),
100		nil,
101		nil,
102		[]objc.MethodDef{
103			{
104				Cmd: objc.RegisterName("doSomething"),
105				Fn: func(self objc.ID, _cmd objc.SEL) {
106					fmt.Println("In Super!")
107				},
108			},
109		},
110	)
111	if err != nil {
112		panic(err)
113	}
114
115	child, err := objc.RegisterClass(
116		"ChildObject",
117		super,
118		nil,
119		nil,
120		[]objc.MethodDef{
121			{
122				Cmd: objc.RegisterName("doSomething"),
123				Fn: func(self objc.ID, _cmd objc.SEL) {
124					fmt.Println("In Child")
125					self.SendSuper(_cmd)
126				},
127			},
128		},
129	)
130	if err != nil {
131		panic(err)
132	}
133
134	objc.ID(child).Send(objc.RegisterName("new")).Send(objc.RegisterName("doSomething"))
135	// Output: In Child
136	// In Super!
137}
138
139func TestSend(t *testing.T) {
140	// NSNumber comes from Foundation so make sure we have linked to that framework.
141	_, err := purego.Dlopen("/System/Library/Frameworks/Foundation.framework/Foundation", purego.RTLD_GLOBAL)
142	if err != nil {
143		t.Fatal(err)
144	}
145	const double = float64(2.34)
146	// Initialize a NSNumber
147	NSNumber := objc.ID(objc.GetClass("NSNumber")).Send(objc.RegisterName("numberWithDouble:"), double)
148	// Then get that number back using the generic Send function.
149	number := objc.Send[float64](NSNumber, objc.RegisterName("doubleValue"))
150	if double != number {
151		t.Failed()
152	}
153}
154
155func ExampleSend() {
156	type NSRange struct {
157		Location, Range uint
158	}
159	class_NSString := objc.GetClass("NSString")
160	sel_stringWithUTF8String := objc.RegisterName("stringWithUTF8String:")
161
162	fullString := objc.ID(class_NSString).Send(sel_stringWithUTF8String, "Hello, World!\x00")
163	subString := objc.ID(class_NSString).Send(sel_stringWithUTF8String, "lo, Wor\x00")
164
165	r := objc.Send[NSRange](fullString, objc.RegisterName("rangeOfString:"), subString)
166	fmt.Println(r)
167	// Output: {3 7}
168}
169
170func ExampleSendSuper() {
171	super, err := objc.RegisterClass(
172		"SuperObject2",
173		objc.GetClass("NSObject"),
174		nil,
175		nil,
176		[]objc.MethodDef{
177			{
178				Cmd: objc.RegisterName("doSomething"),
179				Fn: func(self objc.ID, _cmd objc.SEL) int {
180					return 16
181				},
182			},
183		},
184	)
185	if err != nil {
186		panic(err)
187	}
188
189	child, err := objc.RegisterClass(
190		"ChildObject2",
191		super,
192		nil,
193		nil,
194		[]objc.MethodDef{
195			{
196				Cmd: objc.RegisterName("doSomething"),
197				Fn: func(self objc.ID, _cmd objc.SEL) int {
198					return 24
199				},
200			},
201		},
202	)
203	if err != nil {
204		panic(err)
205	}
206
207	res := objc.SendSuper[int](objc.ID(child).Send(objc.RegisterName("new")), objc.RegisterName("doSomething"))
208	fmt.Println(res)
209	// Output: 16
210}

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 1

Tags 102

↑↓ moveenter openesc close