github.com/ebitengine/purego@v0.8.0-alpha.2.0.20240512170805-6cd12240d332/objc/objc_runtime_darwin_test.go (about) 1 // SPDX-License-Identifier: Apache-2.0 2 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors 3 4 package objc_test 5 6 import ( 7 "fmt" 8 "reflect" 9 "testing" 10 11 "github.com/ebitengine/purego" 12 "github.com/ebitengine/purego/objc" 13 ) 14 15 func 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 39 func 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 87 func 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 96 func 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 139 func 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 155 func 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 170 func 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 }