github.com/tinygo-org/tinygo@v0.31.3-0.20240404173401-90b0bf646c27/testdata/cgo/main.go (about)

     1  package main
     2  
     3  /*
     4  #include <stdio.h>
     5  int fortytwo(void);
     6  #include "main.h"
     7  #include "test.h"
     8  int mul(int, int);
     9  #include <string.h>
    10  #cgo CFLAGS: -DSOME_CONSTANT=17
    11  #define someDefine -5 + 2 * 7
    12  bool someBool;
    13  */
    14  import "C"
    15  
    16  // int headerfunc(int a) { return a + 1; }
    17  // static int headerfunc_static(int a) { return a - 1; }
    18  import "C"
    19  
    20  import "unsafe"
    21  
    22  func main() {
    23  	println("fortytwo:", C.fortytwo())
    24  	println("add:", C.add(C.int(3), 5))
    25  	var x C.myint = 3
    26  	println("myint:", x, C.myint(5))
    27  	println("myint size:", int(unsafe.Sizeof(x)))
    28  	var y C.longlong = -(1 << 40)
    29  	println("longlong:", y)
    30  	println("global:", C.global)
    31  	println("defined ints:", C.CONST_INT, C.CONST_INT2)
    32  	println("defined floats:", C.CONST_FLOAT, C.CONST_FLOAT2)
    33  	println("defined string:", C.CONST_STRING)
    34  	println("defined char:", C.CONST_CHAR)
    35  	println("defined expr:", C.someDefine)
    36  	var ptr C.intPointer
    37  	var n C.int = 15
    38  	ptr = C.intPointer(&n)
    39  	println("15:", *ptr)
    40  	C.store(25, &n)
    41  	println("25:", *ptr)
    42  	cb := C.binop_t(C.add)
    43  	println("callback 1:", C.doCallback(20, 30, cb))
    44  	cb = C.binop_t(C.mul)
    45  	println("callback 2:", C.doCallback(20, 30, cb))
    46  	genericCallbackCall[int]()
    47  
    48  	// variadic functions
    49  	println("variadic0:", C.variadic0())
    50  	println("variadic2:", C.variadic2(3, 5))
    51  
    52  	// functions in the header C snippet
    53  	println("headerfunc:", C.headerfunc(5))
    54  	println("static headerfunc:", C.headerfunc_static(5))
    55  	headerfunc_2()
    56  
    57  	// equivalent types
    58  	var goInt8 int8 = 5
    59  	var _ C.int8_t = goInt8
    60  
    61  	var _ bool = C.someBool
    62  	var _ C._Bool = C.someBool
    63  
    64  	// more globals
    65  	println("bool:", C.globalBool, C.globalBool2 == true)
    66  	println("float:", C.globalFloat)
    67  	println("double:", C.globalDouble)
    68  	println("complex float:", C.globalComplexFloat)
    69  	println("complex double:", C.globalComplexDouble)
    70  	println("complex long double:", C.globalComplexLongDouble)
    71  	println("char match:", C.globalChar == 100)
    72  	var voidPtr unsafe.Pointer = C.globalVoidPtrNull
    73  	println("void* match:", voidPtr == nil, C.globalVoidPtrNull == nil, (*C.int)(C.globalVoidPtrSet) == &C.global)
    74  	println("int64_t match:", C.globalInt64 == C.int64_t(-(2<<40)))
    75  
    76  	// complex types
    77  	println("struct:", C.int(unsafe.Sizeof(C.globalStruct)) == C.globalStructSize, C.globalStruct.s, C.globalStruct.l, C.globalStruct.f)
    78  	var _ [3]C.short = C.globalArray
    79  	println("array:", C.globalArray[0], C.globalArray[1], C.globalArray[2])
    80  	println("union:", C.int(unsafe.Sizeof(C.globalUnion)) == C.globalUnionSize)
    81  	C.unionSetShort(22)
    82  	println("union s:", *C.globalUnion.unionfield_s())
    83  	C.unionSetFloat(C.float(6.28))
    84  	println("union f (C.float):", *C.globalUnion.unionfield_f())
    85  	C.unionSetFloat(float32(3.14))
    86  	println("union f (float32):", *C.globalUnion.unionfield_f())
    87  	C.unionSetData(5, 8, 1)
    88  	data := C.globalUnion.unionfield_data()
    89  	println("union global data:", data[0], data[1], data[2])
    90  	returnedUnion := printUnion(C.globalUnion)
    91  	println("union field:", *returnedUnion.unionfield_f())
    92  	var _ C.union_joined = C.globalUnion
    93  	printBitfield(&C.globalBitfield)
    94  	C.globalBitfield.set_bitfield_a(7)
    95  	C.globalBitfield.set_bitfield_b(0)
    96  	C.globalBitfield.set_bitfield_c(0xff)
    97  	printBitfield(&C.globalBitfield)
    98  
    99  	// elaborated type
   100  	p := C.struct_point2d{x: 3, y: 5}
   101  	println("struct:", p.x, p.y)
   102  
   103  	// multiple anonymous structs (inside a typedef)
   104  	var _ C.point2d_t = C.point2d_t{x: 3, y: 5}
   105  	var _ C.point3d_t = C.point3d_t{x: 3, y: 5, z: 7}
   106  
   107  	// nested structs/unions
   108  	var _ C.tagged_union_t
   109  	var _ C.nested_struct_t
   110  	var _ C.nested_union_t
   111  
   112  	// recursive types, test using a linked list
   113  	list := &C.list_t{n: 3, next: &C.struct_list_t{n: 6, next: &C.list_t{n: 7, next: nil}}}
   114  	for list != nil {
   115  		println("n in chain:", list.n)
   116  		list = (*C.list_t)(list.next)
   117  	}
   118  
   119  	// named enum
   120  	var _ C.enum_option = C.optionA
   121  	var _ C.option_t = C.optionA
   122  	println("option:", C.globalOption)
   123  	println("option A:", C.optionA)
   124  	println("option B:", C.optionB)
   125  	println("option C:", C.optionC)
   126  	println("option D:", C.optionD)
   127  	println("option E:", C.optionE)
   128  	println("option F:", C.optionF)
   129  	println("option G:", C.optionG)
   130  
   131  	// anonymous enum
   132  	var _ C.option2_t = C.option2A
   133  	var _ C.option3_t = C.option3A
   134  	println("option 2A:", C.option2A)
   135  	println("option 3A:", C.option3A)
   136  
   137  	// anonymous structs and enums in multiple Go files
   138  	var _ C.teststruct
   139  	var _ C.testenum
   140  
   141  	// Check that enums are considered the same width in C and CGo.
   142  	println("enum width matches:", unsafe.Sizeof(C.option2_t(0)) == uintptr(C.smallEnumWidth))
   143  
   144  	// Check whether CFLAGS are correctly passed on to compiled C files.
   145  	println("CFLAGS value:", C.cflagsConstant)
   146  
   147  	// Check array-to-pointer decaying. This signature:
   148  	//   void arraydecay(int buf1[5], int buf2[3][8], int buf3[4][7][2]);
   149  	// decays to:
   150  	//   void arraydecay(int *buf1, int *buf2[8], int *buf3[7][2]);
   151  	C.arraydecay((*C.int)(nil), (*[8]C.int)(nil), (*[7][2]C.int)(nil))
   152  
   153  	// Test CGo builtins like C.CString.
   154  	cstr := C.CString("string passed to C")
   155  	println("cstr length:", C.strlen(cstr))
   156  	gostr := C.GoString(cstr)
   157  	println("C.CString:", gostr)
   158  	charBuf := C.GoBytes(unsafe.Pointer(&C.globalChars[0]), 4)
   159  	println("C.charBuf:", charBuf[0], charBuf[1], charBuf[2], charBuf[3])
   160  	binaryString := C.GoStringN(&C.globalChars[0], 4)
   161  	println("C.CStringN:", len(binaryString), binaryString[0], binaryString[1], binaryString[2], binaryString[3])
   162  
   163  	// Test whether those builtins also work with zero length data.
   164  	println("C.GoString(nil):", C.GoString(nil))
   165  	println("len(C.GoStringN(nil, 0)):", len(C.GoStringN(nil, 0)))
   166  	println("len(C.GoBytes(nil, 0)):", len(C.GoBytes(nil, 0)))
   167  
   168  	// libc: test whether C functions work at all.
   169  	buf1 := []byte("foobar\x00")
   170  	buf2 := make([]byte, len(buf1))
   171  	C.strcpy((*C.char)(unsafe.Pointer(&buf2[0])), (*C.char)(unsafe.Pointer(&buf1[0])))
   172  	println("copied string:", string(buf2[:C.strlen((*C.char)(unsafe.Pointer(&buf2[0])))]))
   173  
   174  	// libc: test basic stdio functionality
   175  	putsBuf := []byte("line written using C puts\x00")
   176  	C.puts((*C.char)(unsafe.Pointer(&putsBuf[0])))
   177  }
   178  
   179  func printUnion(union C.joined_t) C.joined_t {
   180  	data := union.unionfield_data()
   181  	println("union local data: ", data[0], data[1], data[2])
   182  	*union.unionfield_s() = -33
   183  	println("union s:", data[0] == -33)
   184  	*union.unionfield_f() = 6.28
   185  	println("union f:", *union.unionfield_f())
   186  	return union
   187  }
   188  
   189  //export mul
   190  func mul(a, b C.int) C.int {
   191  	return a * b
   192  }
   193  
   194  func printBitfield(bitfield *C.bitfield_t) {
   195  	println("bitfield a:", bitfield.bitfield_a())
   196  	println("bitfield b:", bitfield.bitfield_b())
   197  	println("bitfield c:", bitfield.bitfield_c())
   198  	println("bitfield d:", bitfield.d)
   199  	println("bitfield e:", bitfield.e)
   200  }
   201  
   202  type Int interface {
   203  	int | uint
   204  }
   205  
   206  func genericCallbackCall[T Int]() {
   207  	println("callback inside generic function:", C.doCallback(20, 30, C.binop_t(C.add)))
   208  }