--- comments: true date: 2015-03-29 00:28 layout: post tags: golang, c title: Notes on cgo --- ## Referencing c from go. ### Basic operation import "C" imports the C namespace into go, the comment just above this statement is treated as C. ```c /* #include "add.h" */ import "C" ``` Everything you exported from c library is available in the C namespace. ```go func main() { fmt.Println( C.add_two_numbers(3,4) ) } ``` Building code is as easy as `go build` Accessing standard types are easy as `C.char`, `C.int`. For complex types, prepend the type name with an underscore at end – e.g `C.struct_stat`. ### Pointers and memory operations Go provides an `unsafe` module. Go’s GC cannot manage the memory allocated in C code, you should call `C.free(unsafe.Pointer)` (`free` is defined in `` ensure that this library is imported) to deallocate. There are some special functions which convert Go types to C types and vice versa. (lifted from cgo documentation) ```go // Go string to C string // The C string is allocated in the C heap using malloc. // It is the caller's responsibility to arrange for it to be // freed, such as by calling C.free (be sure to include stdlib.h // if C.free is needed). func C.CString(string) *C.char // C string to Go string func C.GoString(*C.char) string // C string, length to Go string func C.GoStringN(*C.char, C.int) string // C pointer, length to Go []byte func C.GoBytes(unsafe.Pointer, C.int) []byte ``` ### Accessing complex objects Accessing structs from Go ```go /* struct person { int age; */ // this can be used in go as var p C.struct_person p.age = 23 ``` You can also pass pointers ```go C.function_accepts_ptr_to_struct(&p) ``` Accessing Unions : No native counterpart, instead of converting it to a type, go treats them as a block of memory represented as byte array. Accessing data is done by casting unsafe.Pointer ```go /* union quant { float weight; int count; }; */ var q C.union_quant ptr := (*float32)(unsafe.Pointer(&q)) *ptr = 3.14 ``` ## Extra goodies ### Compiler Flags Compiler flags can be set using the `#cgo` directive. (`CFLAGS`, `LDFLAGS` etc) ```go /* #cgo: LDFLAGS: -lmath #include */ import "C" ``` ### Restricting building In many cases using cgo breaks the portability of your app, use build constraints to specify compatibility in source. Build constraints are comments which begin with ```go // +build ``` Now, build comment must appear before package clause and should be followed by a blank line To restrict building just to Linux with cgo, ```go // +build linux,cgo !darwin package main ``` These are evaluated as `OR` of each constraint so the above line becomes `(linux AND cgo) OR (NOT darwin)`, also multiple build tags can be embedded in file. There are other methods to restrict builds, see references. ## Reference - [Link to example code gist](https://gist.github.com/dbalan/ace29f0c43638ee4f81d) - [cgo Talk by Rajesh Ramachandran (Gophercon India)](https://www.youtube.com/watch?v=oeEVtyypYPg) - [Conditional compilation with go build](http://dave.cheney.net/2013/10/12/how-to-use-conditional-compilation-with-the-go-build-tool) - [cgo compiler directives](http://golang.org/cmd/cgo/)