Cgo
03.12.2013
package main /* #include <stdlib.h> */ import "C" func Random() int { return int(C.random()) } func Seed(i int) { C.srandom(C.uint(i)) }
#cgo
са "специални"// #cgo CFLAGS: -DPNG_DEBUG=1 // #cgo amd64 386 CFLAGS: -DX86=1 // #cgo LDFLAGS: -lpng // #include <png.h> import "C"
// #cgo pkg-config: png cairo
unsigned int
-> C.uint
C.struct_foo
errno
package foo // extern int goCallbackHandler(int, int); // // static int doAdd(int a, int b) { // return goCallbackHandler(a, b); // } import "C" //export goCallbackHandler func goCallbackHandler(a, b C.int) C.int { return a + b } // This is the public function, callable from outside this package. // It forwards the parameters to C.doAdd(), which in turn forwards // them back to goCallbackHandler(). This one performs the addition // and yields the result. func MyAdd(a, b int) int { return int( C.doAdd( C.int(a), c.int(b)) ) }
foo.MyAdd(a, b) -> C.doAdd(a, b) -> C.goCallbackHandler(a, b) -> foo.goCallbackHandler(a, b)
package foo // #include <somelib.h> // extern int goProgressCB(uint64_t current, uint64_t total, void* userdata); // // static int goGetFiles(some_t* handle, void* userdata) { // return somelib_get_files(handle, goProgressCB, userdata); // } import "C" import "unsafe"
// This defines the signature of our user's progress handler, type ProgressHandler func(current, total uint64, userdata interface{}) int // This is an internal type which will pack the users callback function and userdata. // It is an instance of this type that we will actually be sending to the C code. type progressRequest struct { f ProgressHandler // The user's function pointer d interface{} // The user's userdata. }
//export goProgressCB func goProgressCB(current, total C.uint64_t, userdata unsafe.Pointer) C.int { // This is the function called from the C world by our expensive // C.somelib_get_files() function. The userdata value contains an instance // of *progressRequest, We unpack it and use it's values to call the // actual function that our user supplied. req := (*progressRequest)(userdata) // Call req.f with our parameters and the user's own userdata value. return C.int( req.f( uint64(current), uint64(total), req.d ) ) } // This is our public function, which is called by the user and // takes a handle to something our C lib needs, a function pointer // and optionally some user defined data structure. Whatever it may be. func GetFiles(h *Handle, pf ProgressFunc, userdata interface{}) int { // Instead of calling the external C library directly, we call our C wrapper. // We pass it the handle and an instance of progressRequest. req := unsafe.Pointer(&progressequest{ pf, userdata }) return int(C.goGetFiles( (*C.some_t)(h), req )) }
package main import ( "foo" "fmt" ) func main() { handle := SomeInitStuff() // We call GetFiles. Pass it our progress handler and some // arbitrary userdata (could just as well be nil). ret := foo.GetFiles( handle, myProgress, "Callbacks rock!" ) .... }
// This is our progress handler. Do something useful like display. // progress percentage. func myProgress(current, total uint64, userdata interface{}) int { fc := float64(current) ft := float64(total) * 0.01 // print how far along we are. // eg: 500 / 1000 (50.00%) // For good measure, prefix it with our userdata value, which // we supplied as "Callbacks rock!". fmt.Printf("%s: %d / %d (%3.2f%%)\n", userdata.(string), current, total, fc / ft) return 0 }
foo.GetFiles(....) -> C.goGetFiles(...) -> C.somelib_get_files(..) -> C.goProgressCB(...) -> foo.goProgressCB(...) -> main.myProgress(...)
package main func Add(a, b int) int { return a + b }
#include <stdio.h> extern int go_add(int, int) __asm__ ("example.main.Add"); int main() { int x = go_add(2, 3); printf("Result: %d\n", x); }
all: main main: foo.o bar.c gcc foo.o bar.c -o main foo.o: foo.go gccgo -c foo.go -o foo.o -fgo-prefix=example clean: rm -f main *.o