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  }