github.com/jwijenbergh/purego@v0.0.0-20240126093400-70ff3a61df13/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/jwijenbergh/purego" 12 "github.com/jwijenbergh/purego/objc" 13 ) 14 15 func ExampleAllocateClassPair() { 16 class := objc.AllocateClassPair(objc.GetClass("NSObject"), "FooObject", 0) 17 class.AddMethod(objc.RegisterName("run"), objc.NewIMP(func(self objc.ID, _cmd objc.SEL) { 18 fmt.Println("Hello World!") 19 }), "v@:") 20 class.Register() 21 22 fooObject := objc.ID(class).Send(objc.RegisterName("new")) 23 fooObject.Send(objc.RegisterName("run")) 24 // Output: Hello World! 25 } 26 27 func ExampleRegisterClass() { 28 var ( 29 sel_new = objc.RegisterName("new") 30 sel_init = objc.RegisterName("init") 31 sel_setBar = objc.RegisterName("setBar:") 32 sel_bar = objc.RegisterName("bar") 33 34 BarInit = func(id objc.ID, cmd objc.SEL) objc.ID { 35 return id.SendSuper(cmd) 36 } 37 ) 38 39 class, err := objc.RegisterClass( 40 "BarObject", 41 objc.GetClass("NSObject"), 42 []*objc.Protocol{ 43 objc.GetProtocol("NSDelegateWindow"), 44 }, 45 []objc.FieldDef{ 46 { 47 Name: "bar", 48 Type: reflect.TypeOf(int(0)), 49 Attribute: objc.ReadWrite, 50 }, 51 { 52 Name: "foo", 53 Type: reflect.TypeOf(false), 54 Attribute: objc.ReadWrite, 55 }, 56 }, 57 []objc.MethodDef{ 58 { 59 Cmd: sel_init, 60 Fn: BarInit, 61 }, 62 }, 63 ) 64 if err != nil { 65 panic(err) 66 } 67 68 object := objc.ID(class).Send(sel_new) 69 object.Send(sel_setBar, 123) 70 bar := int(object.Send(sel_bar)) 71 fmt.Println(bar) 72 // Output: 123 73 } 74 75 func ExampleIMP() { 76 imp := objc.NewIMP(func(self objc.ID, _cmd objc.SEL, a3, a4, a5, a6, a7, a8, a9 int) { 77 fmt.Println("IMP:", self, _cmd, a3, a4, a5, a6, a7, a8, a9) 78 }) 79 80 purego.SyscallN(uintptr(imp), 105, 567, 9, 2, 3, ^uintptr(4), 4, 8, 9) 81 82 // Output: IMP: 105 567 9 2 3 -5 4 8 9 83 } 84 85 func ExampleID_SendSuper() { 86 super := objc.AllocateClassPair(objc.GetClass("NSObject"), "SuperObject", 0) 87 super.AddMethod(objc.RegisterName("doSomething"), objc.NewIMP(func(self objc.ID, _cmd objc.SEL) { 88 fmt.Println("In Super!") 89 }), "v@:") 90 super.Register() 91 92 child := objc.AllocateClassPair(super, "ChildObject", 0) 93 child.AddMethod(objc.RegisterName("doSomething"), objc.NewIMP(func(self objc.ID, _cmd objc.SEL) { 94 fmt.Println("In Child") 95 self.SendSuper(_cmd) 96 }), "v@:") 97 child.Register() 98 99 objc.ID(child).Send(objc.RegisterName("new")).Send(objc.RegisterName("doSomething")) 100 101 // Output: In Child 102 // In Super! 103 } 104 105 func TestSend(t *testing.T) { 106 // NSNumber comes from Foundation so make sure we have linked to that framework. 107 _, err := purego.Dlopen("Foundation.framework/Foundation", purego.RTLD_GLOBAL) 108 if err != nil { 109 t.Fatal(err) 110 } 111 const double = float64(2.34) 112 // Initialize a NSNumber 113 NSNumber := objc.ID(objc.GetClass("NSNumber")).Send(objc.RegisterName("numberWithDouble:"), double) 114 // Then get that number back using the generic Send function. 115 number := objc.Send[float64](NSNumber, objc.RegisterName("doubleValue")) 116 if double != number { 117 t.Failed() 118 } 119 }