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 }