├── src ├── Makefile ├── addlib │ ├── addlib.h │ ├── addlib.c │ └── Makefile ├── gofromc │ ├── main.c │ ├── Makefile │ ├── greet.go │ └── greet.h ├── addbin │ ├── Makefile │ └── addbin.c └── badpointers.go ├── cmd ├── c_from_go │ ├── addlib.h │ ├── addlib.c │ └── main.go ├── addbin │ └── main.go └── imagemagick │ └── main.go ├── .gitignore ├── README.md └── Makefile /src/Makefile: -------------------------------------------------------------------------------- 1 | all: 2 | make -C src/addlib 3 | make -C src/addbin 4 | 5 | -------------------------------------------------------------------------------- /cmd/c_from_go/addlib.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | uint32_t add_one(uint32_t val); 4 | -------------------------------------------------------------------------------- /src/addlib/addlib.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | uint32_t add_one(uint32_t val); 4 | -------------------------------------------------------------------------------- /src/addlib/addlib.c: -------------------------------------------------------------------------------- 1 | #include "addlib.h" 2 | 3 | uint32_t add_one(uint32_t val) { 4 | return val + 1; 5 | } 6 | -------------------------------------------------------------------------------- /cmd/c_from_go/addlib.c: -------------------------------------------------------------------------------- 1 | #include "addlib.h" 2 | 3 | uint32_t add_one(uint32_t val) { 4 | return val + 1; 5 | } 6 | -------------------------------------------------------------------------------- /src/gofromc/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "_cgo_export.h" 5 | 6 | int main() { 7 | char *name = "FOSDEM"; 8 | Greet(name); 9 | 10 | return 0; // exit code 11 | } 12 | 13 | -------------------------------------------------------------------------------- /cmd/c_from_go/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | // #include "addlib.h" 4 | import "C" 5 | import "fmt" 6 | 7 | func main() { 8 | num := 10 9 | 10 | added := C.add_one(C.uint32_t(num)) 11 | fmt.Printf("%d + 1 is %d!\n", num, added) 12 | } 13 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /addbin 2 | /c_from_go 3 | /imagemagick 4 | /src/gofromc/_obj/ 5 | /src/gofromc/dy.c 6 | /src/gofromc/greet.a 7 | /src/gofromc/_cgo_export.h 8 | src/gofromc/gofromc 9 | /src/addbin/addbin 10 | /src/addlib/libaddlib.so 11 | /src/addlib/addlib.h.gch 12 | -------------------------------------------------------------------------------- /cmd/addbin/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | // #cgo LDFLAGS: -laddlib 4 | // #include "addlib.h" 5 | import "C" 6 | 7 | import ( 8 | "fmt" 9 | ) 10 | 11 | func main() { 12 | num := C.add_one(10) 13 | fmt.Printf("Go says: %d + one is %d\n", num, C.add_one(num)) 14 | } 15 | -------------------------------------------------------------------------------- /src/addlib/Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: all clean 2 | 3 | CFLAGS=-Wall -Werror -fpic 4 | LDFLAGS=-shared 5 | 6 | all: libaddlib.so 7 | 8 | addlib.o: addlib.c addlib.h 9 | $(CC) $(CFLAGS) -c $^ 10 | 11 | libaddlib.so: addlib.o 12 | $(CC) -o $@ $^ $(LDFLAGS) 13 | 14 | clean: 15 | rm -f libaddlib.so addlib.o 16 | -------------------------------------------------------------------------------- /src/gofromc/Makefile: -------------------------------------------------------------------------------- 1 | all: gofromc 2 | 3 | _cgo_export.h: greet.go 4 | go tool cgo -exportheader $@ $^ 5 | 6 | greet.a: greet.go 7 | go build -buildmode=c-archive $^ 8 | 9 | gofromc: main.c _cgo_export.h greet.a 10 | $(CC) -o $@ $^ -lpthread 11 | 12 | clean: 13 | rm -fr _cgo_export.h greet.a _obj gofromc 14 | -------------------------------------------------------------------------------- /src/addbin/Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: all clean 2 | 3 | all: addbin 4 | 5 | CFLAGS=-Wall -Werror 6 | LDFLAGS=-L"../addlib" 7 | 8 | addbin: addbin.c 9 | # -L"../addlib" 10 | $(CC) $(CFLAGS) -I"../addlib" -o $@ $^ -laddlib $(LDFLAGS) 11 | 12 | run: addbin 13 | LD_LIBRARY_PATH="../addlib:$LD_LIBRARY_PATH" ./addbin 10 14 | 15 | clean: 16 | rm -f addbin 17 | -------------------------------------------------------------------------------- /src/badpointers.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | // #include 4 | // double *global_val; 5 | // void setNum(double *val) { 6 | // global_val = val; 7 | //} 8 | // double *getNum() { 9 | // return global_val; 10 | // } 11 | import "C" 12 | import "fmt" 13 | 14 | func setNum() { 15 | var val = C.double(10) 16 | C.setNum(&val) 17 | } 18 | 19 | func main() { 20 | setNum() 21 | fmt.Printf("%d", int(*C.getNum())) 22 | } 23 | -------------------------------------------------------------------------------- /src/gofromc/greet.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "C" 4 | import "fmt" 5 | 6 | //export Greet 7 | func Greet(chars *C.char) { 8 | str := C.GoString(chars) 9 | fmt.Printf("Hello from Go, %s!\n", str) 10 | } 11 | 12 | func main() {} // required for main package 13 | 14 | type Point struct { 15 | x, y float32 16 | } 17 | 18 | func getPoint() *Point { 19 | return &Point{ 20 | x: 10, 21 | y: 12, 22 | } 23 | } 24 | 25 | func usePoint(pt *Point) { 26 | fmt.Printf("x: %f, y: %f\n", pt.x, pt.y) 27 | // Goes out of scope 28 | } 29 | -------------------------------------------------------------------------------- /src/addbin/addbin.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "addlib.h" 7 | 8 | int main(int argc, char** argv) { 9 | if (argc != 2) { 10 | fprintf(stderr, "Need exactly one argument, got %d\n", argc - 1); 11 | return 1; 12 | } 13 | 14 | char *end; 15 | errno = 0; 16 | uint32_t var = (uint32_t) strtol(argv[1], &end, 10); 17 | switch errno { 18 | case ERANGE: 19 | case EINVAL: 20 | fprintf(stderr, "Invalid number %s\n", argv[1]); 21 | return 1; 22 | } 23 | 24 | printf("C says: %d + one is %d\n", var, add_one(var)); 25 | } 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Cgo Demos 2 | 3 | `make all` 4 | 5 | ## [Addlib](src/addlib) 6 | 7 | _A .so for adding two numbers together_ 8 | 9 | ```shell 10 | make -C src/addlib 11 | ``` 12 | 13 | ## [Addbin](cmd/addbin) 14 | A go library that calls [Addlib](#Addlib) 15 | 16 | ``` 17 | make addbin 18 | LD_LIBRARY_PATH=src/addlib addbin 19 | ``` 20 | 21 | ## [Imagemagick](cmd/imagemagick) 22 | _A small example Go application using libimagemagick_ 23 | 24 | May require `libmagickwand-6-headers` to compile and `libmagickwand-6.q16` 25 | 26 | ```shell 27 | make imagemagick 28 | ./imagemagick 29 | ``` 30 | 31 | ## [C_from_go](cmd/c_from_go) 32 | _An example of calling C from Go_ 33 | 34 | ```shell 35 | make c_from_go 36 | ./c_from_go 37 | ``` 38 | 39 | ## [gofromc](src/gofromc) 40 | An example of calling go from C 41 | 42 | ```shell 43 | make -C src/gofromc 44 | ./gofromc 45 | ``` 46 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: all clean run 2 | 3 | GO?="go" 4 | addlib := $(shell pwd)/src/addlib 5 | 6 | all: 7 | @make -C src/addlib 8 | @make -C src/addbin 9 | @make -C src/gofromc 10 | @make addbin 11 | @make imagemagick 12 | @make cfromgo 13 | 14 | clean: 15 | rm -f addbin c_from_go imagemagick 16 | @make -C src/addlib clean 17 | @make -C src/gofromc clean 18 | @make -C src/addbin clean 19 | 20 | src/addlib/addlib.a: src/addlib/addlib.c 21 | $(CC) 22 | 23 | go_bin: addbin 24 | 25 | addbin: cmd/addbin/main.go src/addlib/addlib.o 26 | CGO_CFLAGS=-I$(addlib) CGO_LDFLAGS=-L$(addlib) $(GO) build github.com/liztio/cgo-demo/cmd/addbin 27 | 28 | imagemagick: cmd/imagemagick/main.go 29 | $(GO) build github.com/liztio/cgo-demo/cmd/imagemagick 30 | 31 | cfromgo: cmd/c_from_go/addlib.c cmd/c_from_go/addlib.h cmd/c_from_go/main.go 32 | $(GO) build github.com/liztio/cgo-demo/cmd/c_from_go 33 | -------------------------------------------------------------------------------- /cmd/imagemagick/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | // #cgo pkg-config: MagickWand 4 | // #include 5 | import "C" 6 | import ( 7 | "flag" 8 | "fmt" 9 | "math" 10 | "os" 11 | ) 12 | 13 | var ( 14 | inputFile = flag.String("in", ":logo", "The file to read in") 15 | outputFile = flag.String("out", "logo.jpg", "The file to write out") 16 | scale = flag.Float64("scale", 0.5, "how much to scale the image by") 17 | ) 18 | 19 | func main() { 20 | flag.Parse() 21 | 22 | if *scale <= 0 { 23 | fmt.Fprintf(os.Stderr, "Scale must be greater than zero\n") 24 | os.Exit(1) 25 | } 26 | 27 | C.MagickWandGenesis() 28 | 29 | // Create a wand 30 | mw := C.NewMagickWand() 31 | 32 | defer func() { 33 | // Tidy up 34 | if mw != nil { 35 | C.DestroyMagickWand(mw) 36 | } 37 | 38 | C.MagickWandTerminus() 39 | }() 40 | 41 | // Read the input image 42 | C.MagickReadImage(mw, C.CString(*inputFile)) 43 | 44 | // Resize it 45 | height := float64(C.MagickGetImageHeight(mw)) 46 | width := float64(C.MagickGetImageWidth(mw)) 47 | 48 | newHeight := math.Round(math.Max(height*(*scale), 1)) 49 | newWidth := math.Round(math.Max(width*(*scale), 1)) 50 | 51 | // Resize the image using the Lanczos filter 52 | // The blur factor is a "double", where > 1 is blurry, < 1 is sharp 53 | C.MagickResizeImage(mw, C.ulong(newWidth), C.ulong(newHeight), C.LanczosFilter, 1) 54 | 55 | // Write the new image 56 | C.MagickWriteImage(mw, C.CString(*outputFile)) 57 | 58 | } 59 | -------------------------------------------------------------------------------- /src/gofromc/greet.h: -------------------------------------------------------------------------------- 1 | /* Code generated by cmd/cgo; DO NOT EDIT. */ 2 | 3 | /* package command-line-arguments */ 4 | 5 | 6 | #line 1 "cgo-builtin-prolog" 7 | 8 | #include /* for ptrdiff_t below */ 9 | 10 | #ifndef GO_CGO_EXPORT_PROLOGUE_H 11 | #define GO_CGO_EXPORT_PROLOGUE_H 12 | 13 | typedef struct { const char *p; ptrdiff_t n; } _GoString_; 14 | 15 | #endif 16 | 17 | /* Start of preamble from import "C" comments. */ 18 | 19 | 20 | 21 | 22 | /* End of preamble from import "C" comments. */ 23 | 24 | 25 | /* Start of boilerplate cgo prologue. */ 26 | #line 1 "cgo-gcc-export-header-prolog" 27 | 28 | #ifndef GO_CGO_PROLOGUE_H 29 | #define GO_CGO_PROLOGUE_H 30 | 31 | typedef signed char GoInt8; 32 | typedef unsigned char GoUint8; 33 | typedef short GoInt16; 34 | typedef unsigned short GoUint16; 35 | typedef int GoInt32; 36 | typedef unsigned int GoUint32; 37 | typedef long long GoInt64; 38 | typedef unsigned long long GoUint64; 39 | typedef GoInt64 GoInt; 40 | typedef GoUint64 GoUint; 41 | typedef __SIZE_TYPE__ GoUintptr; 42 | typedef float GoFloat32; 43 | typedef double GoFloat64; 44 | typedef float _Complex GoComplex64; 45 | typedef double _Complex GoComplex128; 46 | 47 | /* 48 | static assertion to make sure the file is being used on architecture 49 | at least with matching size of GoInt. 50 | */ 51 | typedef char _check_for_64_bit_pointer_matching_GoInt[sizeof(void*)==64/8 ? 1:-1]; 52 | 53 | typedef _GoString_ GoString; 54 | typedef void *GoMap; 55 | typedef void *GoChan; 56 | typedef struct { void *t; void *v; } GoInterface; 57 | typedef struct { void *data; GoInt len; GoInt cap; } GoSlice; 58 | 59 | #endif 60 | 61 | /* End of boilerplate cgo prologue. */ 62 | 63 | #ifdef __cplusplus 64 | extern "C" { 65 | #endif 66 | 67 | 68 | extern void Greet(char* p0); 69 | 70 | #ifdef __cplusplus 71 | } 72 | #endif 73 | --------------------------------------------------------------------------------