v0.8.2 ef7c59a

struct_test.go RawHistoryFolder

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

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 1

Tags 102

↑↓ moveenter openesc close