github.com/graybobo/golang.org-package-offline-cache@v0.0.0-20200626051047-6608995c132f/x/blog/content/c-go-cgo.article (about)

     1  C? Go? Cgo!
     2  17 Mar 2011
     3  Tags: cgo, technical
     4  
     5  Andrew Gerrand
     6  
     7  * Introduction
     8  
     9  Cgo lets Go packages call C code. Given a Go source file written with some special features, cgo outputs Go and C files that can be combined into a single Go package.
    10  
    11  To lead with an example, here's a Go package that provides two functions - `Random` and `Seed` - that wrap C's `random` and `srandom` functions.
    12  
    13  	package rand
    14  
    15  	/*
    16  	#include <stdlib.h>
    17  	*/
    18  	import "C"
    19  
    20  	func Random() int {
    21  	    return int(C.random())
    22  	}
    23  
    24  	func Seed(i int) {
    25  	    C.srandom(C.uint(i))
    26  	}
    27  
    28  Let's look at what's happening here, starting with the import statement.
    29  
    30  The `rand` package imports `"C"`, but you'll find there's no such package in the standard Go library. That's because `C` is a "pseudo-package", a special name interpreted by cgo as a reference to C's name space.
    31  
    32  The `rand` package contains four references to the `C` package: the calls to `C.random` and `C.srandom`, the conversion `C.uint(i)`, and the `import` statement.
    33  
    34  The `Random` function calls the standard C library's `random` function and returns the result.  In C, `random` returns a value of the C type `long`, which cgo represents as the type `C.long`. It must be converted to a Go type before it can be used by Go code outside this package, using an ordinary Go type conversion:
    35  
    36  	func Random() int {
    37  	    return int(C.random())
    38  	}
    39  
    40  Here's an equivalent function that uses a temporary variable to illustrate the type conversion more explicitly:
    41  
    42  	func Random() int {
    43  	    var r C.long = C.random()
    44  	    return int(r)
    45  	}
    46  
    47  The `Seed` function does the reverse, in a way. It takes a regular Go `int`, converts it to the C `unsigned`int` type, and passes it to the C function `srandom`.
    48  
    49  	func Seed(i int) {
    50  	    C.srandom(C.uint(i))
    51  	}
    52  
    53  Note that cgo knows the `unsigned`int` type as `C.uint`; see the [[http://golang.org/cmd/cgo][cgo documentation]] for a complete list of these numeric type names.
    54  
    55  The one detail of this example we haven't examined yet is the comment above the `import` statement.
    56  
    57  	/*
    58  	#include <stdlib.h>
    59  	*/
    60  	import "C"
    61  
    62  Cgo recognizes this comment.  Any lines starting with `#cgo` followed by a space character are removed; these become directives for cgo. The remaining lines are used as a header when compiling the C parts of the package.  In this case those lines are just a single `#include` statement, but they can be almost any C code.  The `#cgo` directives are used to provide flags for the compiler and linker when building the C parts of the package.
    63  
    64  There is a limitation: if your program uses any `//export` directives, then the C code in the comment may only include declarations (`extern`int`f();`), not definitions (`int`f()`{`return`1;`}`).  You can use `//export` directives to make Go functions accessible to C code.
    65  
    66  The `#cgo` and `//export` directives are documented in the [[http://golang.org/cmd/cgo/][cgo documentation]].
    67  
    68  * Strings and things
    69  
    70  Unlike Go, C doesn't have an explicit string type. Strings in C are represented by a zero-terminated array of chars.
    71  
    72  Conversion between Go and C strings is done with the `C.CString`, `C.GoString`, and `C.GoStringN` functions. These conversions make a copy of the string data.
    73  
    74  This next example implements a `Print` function that writes a string to standard output using C's `fputs` function from the `stdio` library:
    75  
    76  	package print
    77  
    78  	// #include <stdio.h>
    79  	// #include <stdlib.h>
    80  	import "C"
    81  	import "unsafe"
    82  
    83  	func Print(s string) {
    84  	    cs := C.CString(s)
    85  	    C.fputs(cs, (*C.FILE)(C.stdout))
    86  	    C.free(unsafe.Pointer(cs))
    87  	}
    88  
    89  Memory allocations made by C code are not known to Go's memory manager. When you create a C string with `C.CString` (or any C memory allocation) you must remember to free the memory when you're done with it by calling `C.free`.
    90  
    91  The call to `C.CString` returns a pointer to the start of the char array, so before the function exits we convert it to an [[http://golang.org/pkg/unsafe/#Pointer][`unsafe.Pointer`]] and release the memory allocation with `C.free`. A common idiom in cgo programs is to [[http://golang.org/doc/articles/defer_panic_recover.html][`defer`]] the free immediately after allocating (especially when the code that follows is more complex than a single function call), as in this rewrite of `Print`:
    92  
    93  	func Print(s string) {
    94  	    cs := C.CString(s)
    95  	    defer C.free(unsafe.Pointer(cs))
    96  	    C.fputs(cs, (*C.FILE)(C.stdout))
    97  	}
    98  
    99  * Building cgo packages
   100  
   101  To build cgo packages, just use [[http://golang.org/cmd/go/#Compile_packages_and_dependencies][`go`build`]] or [[http://golang.org/cmd/go/#Compile_and_install_packages_and_dependencies][`go`install`]] as usual. The go tool recognizes the special `"C"` import and automatically uses cgo for those files.
   102  
   103  * More cgo resources
   104  
   105  The [[http://golang.org/cmd/cgo/][cgo command]] documentation has more detail about the C pseudo-package and the build process. The [[http://golang.org/misc/cgo/][cgo examples]] in the Go tree demonstrate more advanced concepts.
   106  
   107  For a simple, idiomatic example of a cgo-based package, see Russ Cox's [[http://code.google.com/p/gosqlite/source/browse/sqlite/sqlite.go][gosqlite]]. Also, the Go Project Dashboard lists [[https://godashboard.appspot.com/project?tag=cgo][several other cgo packages]].
   108  
   109  Finally, if you're curious as to how all this works internally, take a look at the introductory comment of the runtime package's [[https://golang.org/src/runtime/cgocall.go][cgocall.go]].