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  }