github.com/ebitengine/purego@v0.8.0-alpha.2.0.20240512170805-6cd12240d332/struct_test.go (about)

     1  // SPDX-License-Identifier: Apache-2.0
     2  // SPDX-FileCopyrightText: 2024 The Ebitengine Authors
     3  
     4  //go:build darwin && (arm64 || amd64)
     5  
     6  package purego_test
     7  
     8  import (
     9  	"os"
    10  	"path/filepath"
    11  	"runtime"
    12  	"testing"
    13  	"unsafe"
    14  
    15  	"github.com/ebitengine/purego"
    16  )
    17  
    18  func TestRegisterFunc_structArgs(t *testing.T) {
    19  	libFileName := filepath.Join(t.TempDir(), "structtest.so")
    20  	t.Logf("Build %v", libFileName)
    21  
    22  	if err := buildSharedLib("CC", libFileName, filepath.Join("testdata", "structtest", "struct_test.c")); err != nil {
    23  		t.Fatal(err)
    24  	}
    25  	defer os.Remove(libFileName)
    26  
    27  	lib, err := purego.Dlopen(libFileName, purego.RTLD_NOW|purego.RTLD_GLOBAL)
    28  	if err != nil {
    29  		t.Fatalf("Dlopen(%q) failed: %v", libFileName, err)
    30  	}
    31  
    32  	const (
    33  		expectedUnsigned         = 0xdeadbeef
    34  		expectedSigned           = -123
    35  		expectedOdd              = 12 + 23 + 46
    36  		expectedLong     uint64  = 0xdeadbeefcafebabe
    37  		expectedFloat    float32 = 10
    38  		expectedDouble   float64 = 10
    39  	)
    40  
    41  	{
    42  		type Empty struct{}
    43  		var NoStruct func(Empty) int64
    44  		purego.RegisterLibFunc(&NoStruct, lib, "NoStruct")
    45  		if ret := NoStruct(Empty{}); ret != expectedUnsigned {
    46  			t.Fatalf("NoStruct returned %#x wanted %#x", ret, expectedUnsigned)
    47  		}
    48  	}
    49  	{
    50  		type EmptyEmpty struct{}
    51  		var EmptyEmptyFn func(EmptyEmpty) int64
    52  		purego.RegisterLibFunc(&EmptyEmptyFn, lib, "EmptyEmpty")
    53  		if ret := EmptyEmptyFn(EmptyEmpty{}); ret != expectedUnsigned {
    54  			t.Fatalf("EmptyEmpty returned %#x wanted %#x", ret, expectedUnsigned)
    55  		}
    56  		var EmptyEmptyWithReg func(uint32, EmptyEmpty, uint32) int64
    57  		purego.RegisterLibFunc(&EmptyEmptyWithReg, lib, "EmptyEmptyWithReg")
    58  		if ret := EmptyEmptyWithReg(0xdead, EmptyEmpty{}, 0xbeef); ret != expectedUnsigned {
    59  			t.Fatalf("EmptyEmptyWithReg returned %#x wanted %#x", ret, expectedUnsigned)
    60  		}
    61  	}
    62  	{
    63  		type GreaterThan16Bytes struct {
    64  			x, y, z *int64
    65  		}
    66  		var x, y, z int64 = 0xEF, 0xBE00, 0xDEAD0000
    67  		var GreaterThan16BytesFn func(GreaterThan16Bytes) int64
    68  		purego.RegisterLibFunc(&GreaterThan16BytesFn, lib, "GreaterThan16Bytes")
    69  		if ret := GreaterThan16BytesFn(GreaterThan16Bytes{x: &x, y: &y, z: &z}); ret != expectedUnsigned {
    70  			t.Fatalf("GreaterThan16Bytes returned %#x wanted %#x", ret, expectedUnsigned)
    71  		}
    72  	}
    73  	{
    74  		type GreaterThan16BytesStruct struct {
    75  			a struct {
    76  				x, y, z *int64
    77  			}
    78  		}
    79  		var x, y, z int64 = 0xEF, 0xBE00, 0xDEAD0000
    80  		var GreaterThan16BytesStructFn func(GreaterThan16BytesStruct) int64
    81  		purego.RegisterLibFunc(&GreaterThan16BytesStructFn, lib, "GreaterThan16BytesStruct")
    82  		if ret := GreaterThan16BytesStructFn(GreaterThan16BytesStruct{a: struct{ x, y, z *int64 }{x: &x, y: &y, z: &z}}); ret != expectedUnsigned {
    83  			t.Fatalf("GreaterThan16BytesStructFn returned %#x wanted %#x", ret, expectedUnsigned)
    84  		}
    85  	}
    86  	{
    87  		type GreaterThan16Bytes struct {
    88  			x, y, z *int64
    89  		}
    90  		var x, y, z int64 = 0xEF, 0xBE00, 0xDEAD0000
    91  		var AfterRegisters func(a, b, c, d, e, f, g, h int, bytes GreaterThan16Bytes) int64
    92  		purego.RegisterLibFunc(&AfterRegisters, lib, "AfterRegisters")
    93  		if ret := AfterRegisters(0xD0000000, 0xE000000, 0xA00000, 0xD0000, 0xB000, 0xE00, 0xE0, 0xF, GreaterThan16Bytes{x: &x, y: &y, z: &z}); ret != expectedUnsigned {
    94  			t.Fatalf("AfterRegisters returned %#x wanted %#x", ret, expectedUnsigned)
    95  		}
    96  		var BeforeRegisters func(bytes GreaterThan16Bytes, a, b int64) uint64
    97  		z -= 0xFF
    98  		purego.RegisterLibFunc(&BeforeRegisters, lib, "BeforeRegisters")
    99  		if ret := BeforeRegisters(GreaterThan16Bytes{&x, &y, &z}, 0x0F, 0xF0); ret != expectedUnsigned {
   100  			t.Fatalf("BeforeRegisters returned %#x wanted %#x", ret, expectedUnsigned)
   101  		}
   102  	}
   103  	{
   104  		type IntLessThan16Bytes struct {
   105  			x, y int64
   106  		}
   107  		var IntLessThan16BytesFn func(bytes IntLessThan16Bytes) int64
   108  		purego.RegisterLibFunc(&IntLessThan16BytesFn, lib, "IntLessThan16Bytes")
   109  		if ret := IntLessThan16BytesFn(IntLessThan16Bytes{0xDEAD0000, 0xBEEF}); ret != expectedUnsigned {
   110  			t.Fatalf("IntLessThan16BytesFn returned %#x wanted %#x", ret, expectedUnsigned)
   111  		}
   112  	}
   113  	{
   114  		type FloatLessThan16Bytes struct {
   115  			x, y float32
   116  		}
   117  		var FloatLessThan16BytesFn func(FloatLessThan16Bytes) float32
   118  		purego.RegisterLibFunc(&FloatLessThan16BytesFn, lib, "FloatLessThan16Bytes")
   119  		if ret := FloatLessThan16BytesFn(FloatLessThan16Bytes{3, 7}); ret != expectedFloat {
   120  			t.Fatalf("FloatLessThan16Bytes returned %f wanted %f", ret, expectedFloat)
   121  		}
   122  	}
   123  	{
   124  		type ThreeSmallFields struct {
   125  			x, y, z float32
   126  		}
   127  		var ThreeSmallFieldsFn func(ThreeSmallFields) float32
   128  		purego.RegisterLibFunc(&ThreeSmallFieldsFn, lib, "ThreeSmallFields")
   129  		if ret := ThreeSmallFieldsFn(ThreeSmallFields{1, 2, 7}); ret != expectedFloat {
   130  			t.Fatalf("ThreeSmallFields returned %f wanted %f", ret, expectedFloat)
   131  		}
   132  	}
   133  	{
   134  		type FloatAndInt struct {
   135  			x float32
   136  			y int32
   137  		}
   138  		var FloatAndIntFn func(FloatAndInt) float32
   139  		purego.RegisterLibFunc(&FloatAndIntFn, lib, "FloatAndInt")
   140  		if ret := FloatAndIntFn(FloatAndInt{3, 7}); ret != expectedFloat {
   141  			t.Fatalf("FloatAndIntFn returned %f wanted %f", ret, expectedFloat)
   142  		}
   143  	}
   144  	{
   145  		type DoubleStruct struct {
   146  			x float64
   147  		}
   148  		var DoubleStructFn func(DoubleStruct) float64
   149  		purego.RegisterLibFunc(&DoubleStructFn, lib, "DoubleStruct")
   150  		if ret := DoubleStructFn(DoubleStruct{10}); ret != expectedDouble {
   151  			t.Fatalf("DoubleStruct returned %f wanted %f", ret, expectedDouble)
   152  		}
   153  	}
   154  	{
   155  		type TwoDoubleStruct struct {
   156  			x, y float64
   157  		}
   158  		var TwoDoubleStructFn func(TwoDoubleStruct) float64
   159  		purego.RegisterLibFunc(&TwoDoubleStructFn, lib, "TwoDoubleStruct")
   160  		if ret := TwoDoubleStructFn(TwoDoubleStruct{3, 7}); ret != expectedDouble {
   161  			t.Fatalf("TwoDoubleStruct returned %f wanted %f", ret, expectedDouble)
   162  		}
   163  	}
   164  	{
   165  		type TwoDoubleTwoStruct struct {
   166  			x struct {
   167  				x, y float64
   168  			}
   169  		}
   170  		var TwoDoubleTwoStructFn func(TwoDoubleTwoStruct) float64
   171  		purego.RegisterLibFunc(&TwoDoubleTwoStructFn, lib, "TwoDoubleTwoStruct")
   172  		if ret := TwoDoubleTwoStructFn(TwoDoubleTwoStruct{x: struct{ x, y float64 }{x: 3, y: 7}}); ret != expectedDouble {
   173  			t.Fatalf("TwoDoubleTwoStruct returned %f wanted %f", ret, expectedDouble)
   174  		}
   175  	}
   176  	{
   177  		type ThreeDoubleStruct struct {
   178  			x, y, z float64
   179  		}
   180  		var ThreeDoubleStructFn func(ThreeDoubleStruct) float64
   181  		purego.RegisterLibFunc(&ThreeDoubleStructFn, lib, "ThreeDoubleStruct")
   182  		if ret := ThreeDoubleStructFn(ThreeDoubleStruct{1, 3, 6}); ret != expectedDouble {
   183  			t.Fatalf("ThreeDoubleStructFn returned %f wanted %f", ret, expectedDouble)
   184  		}
   185  	}
   186  	{
   187  		type LargeFloatStruct struct {
   188  			a, b, c, d, e, f float64
   189  		}
   190  		var LargeFloatStructFn func(LargeFloatStruct) float64
   191  		purego.RegisterLibFunc(&LargeFloatStructFn, lib, "LargeFloatStruct")
   192  		if ret := LargeFloatStructFn(LargeFloatStruct{1, 2, 3, 4, 5, -5}); ret != expectedDouble {
   193  			t.Fatalf("LargeFloatStructFn returned %f wanted %f", ret, expectedFloat)
   194  		}
   195  		var LargeFloatStructWithRegs func(a, b, c float64, s LargeFloatStruct) float64
   196  		purego.RegisterLibFunc(&LargeFloatStructWithRegs, lib, "LargeFloatStructWithRegs")
   197  		if ret := LargeFloatStructWithRegs(1, -1, 0, LargeFloatStruct{1, 2, 3, 4, 5, -5}); ret != expectedDouble {
   198  			t.Fatalf("LargeFloatStructWithRegs returned %f wanted %f", ret, expectedFloat)
   199  		}
   200  	}
   201  	{
   202  		type Rect struct {
   203  			x, y, w, h float64
   204  		}
   205  		var RectangleWithRegs func(a, b, c, d, e float64, rect Rect) float64
   206  		purego.RegisterLibFunc(&RectangleWithRegs, lib, "RectangleWithRegs")
   207  		if ret := RectangleWithRegs(1, 2, 3, 4, -2, Rect{1, 2, 3, -4}); ret != expectedDouble {
   208  			t.Fatalf("RectangleWithRegs returned %f wanted %f", ret, expectedDouble)
   209  		}
   210  		var RectangleSubtract func(rect Rect) float64
   211  		purego.RegisterLibFunc(&RectangleSubtract, lib, "RectangleSubtract")
   212  		if ret := RectangleSubtract(Rect{15, 5, 3, 7}); ret != expectedDouble {
   213  			t.Fatalf("RectangleSubtract returned %f wanted %f", ret, expectedDouble)
   214  		}
   215  		var Rectangle func(rect Rect) float64
   216  		purego.RegisterLibFunc(&Rectangle, lib, "Rectangle")
   217  		if ret := Rectangle(Rect{1, 2, 3, 4}); ret != expectedDouble {
   218  			t.Fatalf("Rectangle returned %f wanted %f", ret, expectedFloat)
   219  		}
   220  	}
   221  	{
   222  		type FloatArray struct {
   223  			a [2]float64
   224  		}
   225  		var FloatArrayFn func(rect FloatArray) float64
   226  		purego.RegisterLibFunc(&FloatArrayFn, lib, "FloatArray")
   227  		if ret := FloatArrayFn(FloatArray{a: [2]float64{3, 7}}); ret != expectedDouble {
   228  			t.Fatalf("FloatArray returned %f wanted %f", ret, expectedFloat)
   229  		}
   230  	}
   231  	{
   232  		type UnsignedChar4Bytes struct {
   233  			a, b, c, d byte
   234  		}
   235  		var UnsignedChar4BytesFn func(UnsignedChar4Bytes) uint32
   236  		purego.RegisterLibFunc(&UnsignedChar4BytesFn, lib, "UnsignedChar4Bytes")
   237  		if ret := UnsignedChar4BytesFn(UnsignedChar4Bytes{a: 0xDE, b: 0xAD, c: 0xBE, d: 0xEF}); ret != expectedUnsigned {
   238  			t.Fatalf("UnsignedChar4BytesFn returned %#x wanted %#x", ret, expectedUnsigned)
   239  		}
   240  	}
   241  	{
   242  		type UnsignedChar4BytesStruct struct {
   243  			x struct {
   244  				a byte
   245  			}
   246  			y struct {
   247  				b byte
   248  			}
   249  			z struct {
   250  				c byte
   251  			}
   252  			w struct {
   253  				d byte
   254  			}
   255  		}
   256  		var UnsignedChar4BytesStructFn func(UnsignedChar4BytesStruct) uint32
   257  		purego.RegisterLibFunc(&UnsignedChar4BytesStructFn, lib, "UnsignedChar4BytesStruct")
   258  		if ret := UnsignedChar4BytesStructFn(UnsignedChar4BytesStruct{
   259  			x: struct{ a byte }{a: 0xDE},
   260  			y: struct{ b byte }{b: 0xAD},
   261  			z: struct{ c byte }{c: 0xBE},
   262  			w: struct{ d byte }{d: 0xEF},
   263  		}); ret != expectedUnsigned {
   264  			t.Fatalf("UnsignedChar4BytesStructFn returned %#x wanted %#x", ret, expectedUnsigned)
   265  		}
   266  	}
   267  	{
   268  		type Short struct {
   269  			a, b, c, d uint16
   270  		}
   271  		var ShortFn func(Short) uint64
   272  		purego.RegisterLibFunc(&ShortFn, lib, "Short")
   273  		if ret := ShortFn(Short{a: 0xDEAD, b: 0xBEEF, c: 0xCAFE, d: 0xBABE}); ret != expectedLong {
   274  			t.Fatalf("ShortFn returned %#x wanted %#x", ret, expectedLong)
   275  		}
   276  	}
   277  	{
   278  		type Int struct {
   279  			a, b uint32
   280  		}
   281  		var IntFn func(Int) uint64
   282  		purego.RegisterLibFunc(&IntFn, lib, "Int")
   283  		if ret := IntFn(Int{a: 0xDEADBEEF, b: 0xCAFEBABE}); ret != expectedLong {
   284  			t.Fatalf("IntFn returned %#x wanted %#x", ret, expectedLong)
   285  		}
   286  	}
   287  	{
   288  		type Long struct {
   289  			a uint64
   290  		}
   291  		var LongFn func(Long) uint64
   292  		purego.RegisterLibFunc(&LongFn, lib, "Long")
   293  		if ret := LongFn(Long{a: 0xDEADBEEFCAFEBABE}); ret != expectedLong {
   294  			t.Fatalf("LongFn returned %#x wanted %#x", ret, expectedLong)
   295  		}
   296  	}
   297  	{
   298  		type Char8Bytes struct {
   299  			a, b, c, d, e, f, g, h int8
   300  		}
   301  		var Char8BytesFn func(Char8Bytes) int32
   302  		purego.RegisterLibFunc(&Char8BytesFn, lib, "Char8Bytes")
   303  		if ret := Char8BytesFn(Char8Bytes{a: -128, b: 127, c: 3, d: -88, e: -3, f: 34, g: -48, h: -20}); ret != expectedSigned {
   304  			t.Fatalf("Char8Bytes returned %d wanted %d", ret, expectedSigned)
   305  		}
   306  	}
   307  	{
   308  		type Odd struct {
   309  			a, b, c byte
   310  		}
   311  		var OddFn func(Odd) int32
   312  		purego.RegisterLibFunc(&OddFn, lib, "Odd")
   313  		if ret := OddFn(Odd{a: 12, b: 23, c: 46}); ret != expectedOdd {
   314  			t.Fatalf("OddFn returned %d wanted %d", ret, expectedOdd)
   315  		}
   316  	}
   317  	{
   318  		type Char2Short1 struct {
   319  			a, b byte
   320  			c    uint16
   321  		}
   322  		var Char2Short1s func(Char2Short1) int32
   323  		purego.RegisterLibFunc(&Char2Short1s, lib, "Char2Short1s")
   324  		if ret := Char2Short1s(Char2Short1{a: 12, b: 23, c: 46}); ret != expectedOdd {
   325  			t.Fatalf("Char2Short1s returned %d wanted %d", ret, expectedOdd)
   326  		}
   327  	}
   328  	{
   329  		type SignedChar2Short1 struct {
   330  			a, b int8
   331  			c    int16
   332  		}
   333  		var SignedChar2Short1Fn func(SignedChar2Short1) int32
   334  		purego.RegisterLibFunc(&SignedChar2Short1Fn, lib, "SignedChar2Short1")
   335  		if ret := SignedChar2Short1Fn(SignedChar2Short1{a: 100, b: -23, c: -200}); ret != expectedSigned {
   336  			t.Fatalf("SignedChar2Short1Fn returned %d wanted %d", ret, expectedSigned)
   337  		}
   338  	}
   339  	{
   340  		type Array4UnsignedChars struct {
   341  			a [4]uint8
   342  		}
   343  		var Array4UnsignedCharsFn func(chars Array4UnsignedChars) uint32
   344  		purego.RegisterLibFunc(&Array4UnsignedCharsFn, lib, "Array4UnsignedChars")
   345  		if ret := Array4UnsignedCharsFn(Array4UnsignedChars{a: [...]uint8{0xDE, 0xAD, 0xBE, 0xEF}}); ret != expectedUnsigned {
   346  			t.Fatalf("Array4UnsignedCharsFn returned %#x wanted %#x", ret, expectedUnsigned)
   347  		}
   348  	}
   349  	{
   350  		type Array3UnsignedChar struct {
   351  			a [3]uint8
   352  		}
   353  		var Array3UnsignedChars func(chars Array3UnsignedChar) uint32
   354  		purego.RegisterLibFunc(&Array3UnsignedChars, lib, "Array3UnsignedChars")
   355  		if ret := Array3UnsignedChars(Array3UnsignedChar{a: [...]uint8{0xDE, 0xAD, 0xBE}}); ret != expectedUnsigned {
   356  			t.Fatalf("Array4UnsignedCharsFn returned %#x wanted %#x", ret, expectedUnsigned)
   357  		}
   358  	}
   359  	{
   360  		type Array2UnsignedShort struct {
   361  			a [2]uint16
   362  		}
   363  		var Array2UnsignedShorts func(chars Array2UnsignedShort) uint32
   364  		purego.RegisterLibFunc(&Array2UnsignedShorts, lib, "Array2UnsignedShorts")
   365  		if ret := Array2UnsignedShorts(Array2UnsignedShort{a: [...]uint16{0xDEAD, 0xBEEF}}); ret != expectedUnsigned {
   366  			t.Fatalf("Array4UnsignedCharsFn returned %#x wanted %#x", ret, expectedUnsigned)
   367  		}
   368  	}
   369  	{
   370  		type Array4Chars struct {
   371  			a [4]int8
   372  		}
   373  		var Array4CharsFn func(chars Array4Chars) int32
   374  		purego.RegisterLibFunc(&Array4CharsFn, lib, "Array4Chars")
   375  		if ret := Array4CharsFn(Array4Chars{a: [...]int8{100, -127, 4, -100}}); ret != expectedSigned {
   376  			t.Fatalf("Array4CharsFn returned %#x wanted %#x", ret, expectedSigned)
   377  		}
   378  	}
   379  	{
   380  		type Array2Short struct {
   381  			a [2]int16
   382  		}
   383  		var Array2Shorts func(chars Array2Short) int32
   384  		purego.RegisterLibFunc(&Array2Shorts, lib, "Array2Shorts")
   385  		if ret := Array2Shorts(Array2Short{a: [...]int16{-333, 210}}); ret != expectedSigned {
   386  			t.Fatalf("Array4Shorts returned %#x wanted %#x", ret, expectedSigned)
   387  		}
   388  	}
   389  	{
   390  		type Array3Short struct {
   391  			a [3]int16
   392  		}
   393  		var Array3Shorts func(chars Array3Short) int32
   394  		purego.RegisterLibFunc(&Array3Shorts, lib, "Array3Shorts")
   395  		if ret := Array3Shorts(Array3Short{a: [...]int16{-333, 100, 110}}); ret != expectedSigned {
   396  			t.Fatalf("Array4Shorts returned %#x wanted %#x", ret, expectedSigned)
   397  		}
   398  	}
   399  	{
   400  		type BoolStruct struct {
   401  			b bool
   402  		}
   403  		var BoolStructFn func(BoolStruct) bool
   404  		purego.RegisterLibFunc(&BoolStructFn, lib, "BoolStruct")
   405  		if ret := BoolStructFn(BoolStruct{true}); ret != true {
   406  			t.Fatalf("BoolStructFn returned %v wanted %v", ret, true)
   407  		}
   408  		if ret := BoolStructFn(BoolStruct{false}); ret != false {
   409  			t.Fatalf("BoolStructFn returned %v wanted %v", ret, false)
   410  		}
   411  	}
   412  	{
   413  		type BoolFloat struct {
   414  			b bool
   415  			_ [3]byte // purego won't do padding for you so make sure it aligns properly with C struct
   416  			f float32
   417  		}
   418  		var BoolFloatFn func(BoolFloat) float32
   419  		purego.RegisterLibFunc(&BoolFloatFn, lib, "BoolFloat")
   420  		if ret := BoolFloatFn(BoolFloat{b: true, f: 10}); ret != expectedFloat {
   421  			t.Fatalf("BoolFloatFn returned %f wanted %f", ret, expectedFloat)
   422  		}
   423  		if ret := BoolFloatFn(BoolFloat{b: false, f: 10}); ret != -expectedFloat {
   424  			t.Fatalf("BoolFloatFn returned %f wanted %f", ret, -expectedFloat)
   425  		}
   426  	}
   427  	{
   428  		type point struct{ x, y float64 }
   429  		type size struct{ width, height float64 }
   430  		type Content struct {
   431  			point point
   432  			size  size
   433  		}
   434  		var InitWithContentRect func(*int, Content, int32, int32, bool) uint64
   435  		purego.RegisterLibFunc(&InitWithContentRect, lib, "InitWithContentRect")
   436  		if ret := InitWithContentRect(new(int),
   437  			// These numbers are created so that when added together and then divided by 11 it produces 0xdeadbeef
   438  			Content{point{x: 41_000_000_000, y: 95_000_000}, size{width: 214_000, height: 149}},
   439  			15, 4, true); ret != expectedUnsigned {
   440  			t.Fatalf("InitWithContentRect returned %d wanted %#x", ret, expectedUnsigned)
   441  		}
   442  	}
   443  }
   444  
   445  func TestRegisterFunc_structReturns(t *testing.T) {
   446  	libFileName := filepath.Join(t.TempDir(), "structreturntest.so")
   447  	t.Logf("Build %v", libFileName)
   448  
   449  	if err := buildSharedLib("CC", libFileName, filepath.Join("testdata", "structtest", "structreturn_test.c")); err != nil {
   450  		t.Fatal(err)
   451  	}
   452  	defer os.Remove(libFileName)
   453  
   454  	lib, err := purego.Dlopen(libFileName, purego.RTLD_NOW|purego.RTLD_GLOBAL)
   455  	if err != nil {
   456  		t.Fatalf("Dlopen(%q) failed: %v", libFileName, err)
   457  	}
   458  
   459  	{
   460  		type Empty struct{}
   461  		var ReturnEmpty func() Empty
   462  		purego.RegisterLibFunc(&ReturnEmpty, lib, "ReturnEmpty")
   463  		ret := ReturnEmpty()
   464  		_ = ret
   465  	}
   466  	{
   467  		type inner struct{ a int16 }
   468  		type StructInStruct struct {
   469  			a inner
   470  			b inner
   471  			c inner
   472  		}
   473  		var ReturnStructInStruct func(a, b, c int16) StructInStruct
   474  		purego.RegisterLibFunc(&ReturnStructInStruct, lib, "ReturnStructInStruct")
   475  		expected := StructInStruct{inner{^int16(0)}, inner{2}, inner{3}}
   476  		if ret := ReturnStructInStruct(^int16(0), 2, 3); ret != expected {
   477  			t.Fatalf("StructInStruct returned %+v wanted %+v", ret, expected)
   478  		}
   479  	}
   480  	{
   481  		type ThreeShorts struct{ a, b, c int16 }
   482  		var ReturnThreeShorts func(a, b, c int16) ThreeShorts
   483  		purego.RegisterLibFunc(&ReturnThreeShorts, lib, "ReturnThreeShorts")
   484  		expected := ThreeShorts{^int16(0), 2, 3}
   485  		if ret := ReturnThreeShorts(^int16(0), 2, 3); ret != expected {
   486  			t.Fatalf("ReturnThreeShorts returned %+v wanted %+v", ret, expected)
   487  		}
   488  	}
   489  	{
   490  		type FourShorts struct{ a, b, c, d int16 }
   491  		var ReturnFourShorts func(a, b, c, d int16) FourShorts
   492  		purego.RegisterLibFunc(&ReturnFourShorts, lib, "ReturnFourShorts")
   493  		expected := FourShorts{^int16(0), 2, 3, 4}
   494  		if ret := ReturnFourShorts(^int16(0), 2, 3, 4); ret != expected {
   495  			t.Fatalf("ReturnFourShorts returned %+v wanted %+v", ret, expected)
   496  		}
   497  	}
   498  	{
   499  		type OneLong struct{ a int64 }
   500  		var ReturnOneLong func(a int64) OneLong
   501  		purego.RegisterLibFunc(&ReturnOneLong, lib, "ReturnOneLong")
   502  		expected := OneLong{5}
   503  		if ret := ReturnOneLong(5); ret != expected {
   504  			t.Fatalf("ReturnOneLong returned %+v wanted %+v", ret, expected)
   505  		}
   506  	}
   507  	{
   508  		type TwoLongs struct{ a, b int64 }
   509  		var ReturnTwoLongs func(a, b int64) TwoLongs
   510  		purego.RegisterLibFunc(&ReturnTwoLongs, lib, "ReturnTwoLongs")
   511  		expected := TwoLongs{1, 2}
   512  		if ret := ReturnTwoLongs(1, 2); ret != expected {
   513  			t.Fatalf("ReturnTwoLongs returned %+v wanted %+v", ret, expected)
   514  		}
   515  	}
   516  	{
   517  		type ThreeLongs struct{ a, b, c int64 }
   518  		var ReturnThreeLongs func(a, b, c int64) ThreeLongs
   519  		purego.RegisterLibFunc(&ReturnThreeLongs, lib, "ReturnThreeLongs")
   520  		expected := ThreeLongs{1, 2, 3}
   521  		if ret := ReturnThreeLongs(1, 2, 3); ret != expected {
   522  			t.Fatalf("ReturnThreeLongs returned %+v wanted %+v", ret, expected)
   523  		}
   524  	}
   525  	{
   526  		type OneFloat struct{ a float32 }
   527  		var ReturnOneFloat func(a float32) OneFloat
   528  		purego.RegisterLibFunc(&ReturnOneFloat, lib, "ReturnOneFloat")
   529  		expected := OneFloat{1}
   530  		if ret := ReturnOneFloat(1); ret != expected {
   531  			t.Fatalf("ReturnOneFloat returned %+v wanted %+v", ret, expected)
   532  		}
   533  	}
   534  	{
   535  		type TwoFloats struct{ a, b float32 }
   536  		var ReturnTwoFloats func(a, b float32) TwoFloats
   537  		purego.RegisterLibFunc(&ReturnTwoFloats, lib, "ReturnTwoFloats")
   538  		expected := TwoFloats{3, 10}
   539  		if ret := ReturnTwoFloats(5, 2); ret != expected {
   540  			t.Fatalf("ReturnTwoFloats returned %+v wanted %+v", ret, expected)
   541  		}
   542  	}
   543  	{
   544  		type ThreeFloats struct{ a, b, c float32 }
   545  		var ReturnThreeFloats func(a, b, c float32) ThreeFloats
   546  		purego.RegisterLibFunc(&ReturnThreeFloats, lib, "ReturnThreeFloats")
   547  		expected := ThreeFloats{1, 2, 3}
   548  		if ret := ReturnThreeFloats(1, 2, 3); ret != expected {
   549  			t.Fatalf("ReturnThreeFloats returned %+v wanted %+v", ret, expected)
   550  		}
   551  	}
   552  	{
   553  		type OneDouble struct{ a float64 }
   554  		var ReturnOneDouble func(a float64) OneDouble
   555  		purego.RegisterLibFunc(&ReturnOneDouble, lib, "ReturnOneDouble")
   556  		expected := OneDouble{1}
   557  		if ret := ReturnOneDouble(1); ret != expected {
   558  			t.Fatalf("ReturnOneDouble returned %+v wanted %+v", ret, expected)
   559  		}
   560  	}
   561  	{
   562  		type TwoDoubles struct{ a, b float64 }
   563  		var ReturnTwoDoubles func(a, b float64) TwoDoubles
   564  		purego.RegisterLibFunc(&ReturnTwoDoubles, lib, "ReturnTwoDoubles")
   565  		expected := TwoDoubles{1, 2}
   566  		if ret := ReturnTwoDoubles(1, 2); ret != expected {
   567  			t.Fatalf("ReturnTwoDoubles returned %+v wanted %+v", ret, expected)
   568  		}
   569  	}
   570  	{
   571  		type ThreeDoubles struct{ a, b, c float64 }
   572  		var ReturnThreeDoubles func(a, b, c float64) ThreeDoubles
   573  		purego.RegisterLibFunc(&ReturnThreeDoubles, lib, "ReturnThreeDoubles")
   574  		expected := ThreeDoubles{1, 2, 3}
   575  		if ret := ReturnThreeDoubles(1, 2, 3); ret != expected {
   576  			t.Fatalf("ReturnThreeDoubles returned %+v wanted %+v", ret, expected)
   577  		}
   578  	}
   579  	{
   580  		type FourDoubles struct{ a, b, c, d float64 }
   581  		var ReturnFourDoubles func(a, b, c, d float64) FourDoubles
   582  		purego.RegisterLibFunc(&ReturnFourDoubles, lib, "ReturnFourDoubles")
   583  		expected := FourDoubles{1, 2, 3, 4}
   584  		if ret := ReturnFourDoubles(1, 2, 3, 4); ret != expected {
   585  			t.Fatalf("ReturnFourDoubles returned %+v wanted %+v", ret, expected)
   586  		}
   587  	}
   588  	{
   589  		type FourDoublesInternal struct {
   590  			f struct{ a, b float64 }
   591  			g struct{ c, d float64 }
   592  		}
   593  		var ReturnFourDoublesInternal func(a, b, c, d float64) FourDoublesInternal
   594  		purego.RegisterLibFunc(&ReturnFourDoublesInternal, lib, "ReturnFourDoublesInternal")
   595  		expected := FourDoublesInternal{f: struct{ a, b float64 }{a: 1, b: 2}, g: struct{ c, d float64 }{c: 3, d: 4}}
   596  		if ret := ReturnFourDoublesInternal(1, 2, 3, 4); ret != expected {
   597  			t.Fatalf("ReturnFourDoublesInternal returned %+v wanted %+v", ret, expected)
   598  		}
   599  	}
   600  	{
   601  		type FiveDoubles struct{ a, b, c, d, e float64 }
   602  		var ReturnFiveDoubles func(a, b, c, d, e float64) FiveDoubles
   603  		purego.RegisterLibFunc(&ReturnFiveDoubles, lib, "ReturnFiveDoubles")
   604  		expected := FiveDoubles{1, 2, 3, 4, 5}
   605  		if ret := ReturnFiveDoubles(1, 2, 3, 4, 5); ret != expected {
   606  			t.Fatalf("ReturnFiveDoubles returned %+v wanted %+v", ret, expected)
   607  		}
   608  	}
   609  	{
   610  		type OneFloatOneDouble struct {
   611  			a float32
   612  			_ float32
   613  			b float64
   614  		}
   615  		var ReturnOneFloatOneDouble func(a float32, b float64) OneFloatOneDouble
   616  		purego.RegisterLibFunc(&ReturnOneFloatOneDouble, lib, "ReturnOneFloatOneDouble")
   617  		expected := OneFloatOneDouble{a: 1, b: 2}
   618  		if ret := ReturnOneFloatOneDouble(1, 2); ret != expected {
   619  			t.Fatalf("ReturnOneFloatOneDouble returned %+v wanted %+v", ret, expected)
   620  		}
   621  	}
   622  	{
   623  		type OneDoubleOneFloat struct {
   624  			a float64
   625  			b float32
   626  		}
   627  		var ReturnOneDoubleOneFloat func(a float64, b float32) OneDoubleOneFloat
   628  		purego.RegisterLibFunc(&ReturnOneDoubleOneFloat, lib, "ReturnOneDoubleOneFloat")
   629  		expected := OneDoubleOneFloat{1, 2}
   630  		if ret := ReturnOneDoubleOneFloat(1, 2); ret != expected {
   631  			t.Fatalf("ReturnOneDoubleOneFloat returned %+v wanted %+v", ret, expected)
   632  		}
   633  	}
   634  	{
   635  		type Unaligned1 struct {
   636  			a int8
   637  			_ [1]int8
   638  			b int16
   639  			_ [1]int32
   640  			c int64
   641  		}
   642  		var ReturnUnaligned1 func(a int8, b int16, c int64) Unaligned1
   643  		purego.RegisterLibFunc(&ReturnUnaligned1, lib, "ReturnUnaligned1")
   644  		expected := Unaligned1{a: 1, b: 2, c: 3}
   645  		if ret := ReturnUnaligned1(1, 2, 3); ret != expected {
   646  			t.Fatalf("ReturnUnaligned1 returned %+v wanted %+v", ret, expected)
   647  		}
   648  	}
   649  	{
   650  		type Mixed1 struct {
   651  			a float32
   652  			b int32
   653  		}
   654  		var ReturnMixed1 func(a float32, b int32) Mixed1
   655  		purego.RegisterLibFunc(&ReturnMixed1, lib, "ReturnMixed1")
   656  		expected := Mixed1{1, 2}
   657  		if ret := ReturnMixed1(1, 2); ret != expected {
   658  			t.Fatalf("ReturnMixed1 returned %+v wanted %+v", ret, expected)
   659  		}
   660  	}
   661  	{
   662  		type Mixed2 struct {
   663  			a float32
   664  			b int32
   665  			c float32
   666  			d int32
   667  		}
   668  		var ReturnMixed2 func(a float32, b int32, c float32, d int32) Mixed2
   669  		purego.RegisterLibFunc(&ReturnMixed2, lib, "ReturnMixed2")
   670  		expected := Mixed2{1, 2, 3, 4}
   671  		if ret := ReturnMixed2(1, 2, 3, 4); ret != expected {
   672  			t.Fatalf("ReturnMixed2 returned %+v wanted %+v", ret, expected)
   673  		}
   674  	}
   675  	{
   676  		type Mixed3 struct {
   677  			a float32
   678  			b uint32
   679  			c float64
   680  		}
   681  		var ReturnMixed3 func(a float32, b uint32, c float64) Mixed3
   682  		purego.RegisterLibFunc(&ReturnMixed3, lib, "ReturnMixed3")
   683  		expected := Mixed3{1, 2, 3}
   684  		if ret := ReturnMixed3(1, 2, 3); ret != expected {
   685  			t.Fatalf("ReturnMixed3 returned %+v wanted %+v", ret, expected)
   686  		}
   687  	}
   688  	{
   689  		type Mixed4 struct {
   690  			a float64
   691  			b uint32
   692  			c float32
   693  		}
   694  		var ReturnMixed4 func(a float64, b uint32, c float32) Mixed4
   695  		purego.RegisterLibFunc(&ReturnMixed4, lib, "ReturnMixed4")
   696  		expected := Mixed4{1, 2, 3}
   697  		if ret := ReturnMixed4(1, 2, 3); ret != expected {
   698  			t.Fatalf("ReturnMixed4 returned %+v wanted %+v", ret, expected)
   699  		}
   700  	}
   701  	{
   702  		type Ptr1 struct {
   703  			a *int64
   704  			b unsafe.Pointer
   705  		}
   706  		var ReturnPtr1 func(a *int64, b unsafe.Pointer) Ptr1
   707  		purego.RegisterLibFunc(&ReturnPtr1, lib, "ReturnPtr1")
   708  		a, b := new(int64), new(struct{})
   709  		expected := Ptr1{a, unsafe.Pointer(b)}
   710  		if ret := ReturnPtr1(a, unsafe.Pointer(b)); ret != expected {
   711  			t.Fatalf("ReturnPtr1 returned %+v wanted %+v", ret, expected)
   712  		}
   713  		runtime.KeepAlive(a)
   714  		runtime.KeepAlive(b)
   715  	}
   716  }