CGo for fun and profit

L
github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta
Foreign Functions for
Fun and Profit
When and how to use CGo
github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta
github.com/liztio/cgo-demo
github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta
github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta
github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta
@stillinbeta
github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta
github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta
recurse.com
github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta
Renee French. (http://reneefrench.blogspot.com/)
github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta
Full disclosure?
...I don’t actually like Go very much.
github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta
but I use it a lot
github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta
Why not Cgo?
github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta
cgo is not Go - Dave Cheney
bit.ly/cgo-not-go
github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta
Why not Cgo
● More complicated compilation
● Less portable
● No cross compilation
● More segfaults
● No backtraces
● Less tooling
github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta
Why Cgo
● ...sometimes it’s the only way
github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta
Calling C from Go
github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta
#include <stdint.h>
uint32_t add_one(uint32_t val);
addlib.h
#include "addlib.h"
uint32_t add_one(uint32_t val)
{
return val + 1;
}
addlib.c
github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta
uint32_t
Unsigned integer 32 bit type
github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta
import "C"
github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta
// #include "addlib.h"
import "C"
github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta
added := C.add_one(num)
github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta
main.go
package main
// #include "addlib.h"
import "C" // “C” always gets its own line
import "fmt"
func main() {
num := 10
added := C.add_one(num)
fmt.Printf("%d + 1 is %d!n", num, added)
}
github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta
$ go run github.com/liztio/cgo-demo/cmd/c_from_go
github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta
$ go run github.com/liztio/cgo-demo/cmd/c_from_go
# github.com/liztio/cgo-demo/cmd/c_from_go
cmd/c_from_go/main.go:10:27: cannot use num (type
int) as type _Ctype_uint in argument to
_Cfunc_add_one
github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta
added := C.add_one(C.uint32_t(num))
github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta
$ go run github.com/liztio/cgo-demo/cmd/c_from_go
10 + 1 is 11!
github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta
Calling Go from C
github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta
//export Greet
func Greet(chars *C.char) {
str := C.GoString(chars)
fmt.Printf("Hello from Go, %s!n", str)
}
github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta
//export Greet
func Greet(chars *C.char) {
str := C.GoString(chars)
fmt.Printf("Hello from Go, %s!n", str)
}
github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta
//export Greet
func Greet(chars *C.char) {
str := C.GoString(chars)
fmt.Printf("Hello from Go, %s!n", str)
}
github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta
F O S D E M x00
Strings in C
github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta
F O S D E M x00
46 4F 53 44 45 4d 00
Strings in C
github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta
F O S D E M
*ptr 6
Strings in Go
github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta
//export Greet
func Greet(chars *C.char) {
str := C.GoString(chars)
fmt.Printf("Hello from Go, %s!n", str)
}
github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta
package main
import "C"
import "fmt"
//export Greet
func Greet(chars *C.char) {
str := C.GoString(chars)
fmt.Printf("Hello from Go, %s!n", str)
}
func main() {} // required for main package
greet.go
github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta
main.c
#include "_cgo_export.h"
int main() {
char *name = "FOSDEM";
Greet(name);
return 0; // exit code
}
github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta
_cgo_export.h
/* Code generated by cmd/cgo; DO NOT EDIT. */
/* package main */
#line 1 "cgo-builtin-prolog"
#include <stddef.h> /* for ptrdiff_t below */
#ifndef GO_CGO_EXPORT_PROLOGUE_H
#define GO_CGO_EXPORT_PROLOGUE_H
typedef struct { const char *p; ptrdiff_t n; }
_GoString_;
#endif
/* Start of preamble from import "C" comments.
*/
/* End of preamble from import "C" comments.
*/
/* Start of boilerplate cgo prologue. */
github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta
_cgo_export.h
/* don't worry about it */
github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta
A brief introduction to Makefiles
github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta
A brief introduction to Makefiles
all: output
output: input1 input2 input3
command --output $@ --inputs $^
github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta
A brief introduction to Makefiles
all: output
output: input1 input2 input3
command --output output --inputs input1 input2 input3
github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta
Our Makefile
_cgo_export.h: greet.go
go tool cgo -exportheader $@ $^
greet.a: greet.go
go build -buildmode=c-archive $^
gofromc: main.c _cgo_export.h greet.a
$(CC) -o $@ $^ -lpthread
github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta
Our Makefile
_cgo_export.h: greet.go
go tool cgo -exportheader $@ $^
github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta
Our Makefile
greet.a: greet.go
go build -buildmode=c-archive $^
github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta
Our Makefile
gofromc: main.c _cgo_export.h greet.a
$(CC) -o $@ $^ -lpthread
github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta
$ make
go tool cgo -exportheader _cgo_export.h greet.go
go build -buildmode=c-archive greet.go
cc -o gofromc main.c _cgo_export.h greet.a -lpthread
github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta
Let’s try it out!
$ ./gofromc
Hello from Go, FOSDEM!
github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta
Pointers and Memory
github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta
Go Memory
● new() / &value
● Garbage Collected
● malloc()
● Manually Freed with free()
C Memory
github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta
Allocating in Go
type Point struct {
x, y float32
}
func getPoint() *Point {
return &Point{
x: 10,
y: 12,
}
}
typedef struct {
float x;
float y;
} Point;
Point *getPoint() {
Point *pt = malloc(sizeof(Point));
pt->x = 10;
pt->y = 12;
return pt;
}
Allocating in C
github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta
Go
func usePoint(pt *Point) {
fmt.Printf("x: %f, y: %fn", pt.x, pt.y)
// Goes out of scope
}
void usePoint(Point *pt) {
printf("x: %f, y: %fn", pt->x, pt->y);
free(pt);
}
C
github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta
What happens if you forget to free?
$ ./gofromc
x: 10.000000, y: 12.000000
github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta
What happens if you forget to free?
$ valgrind --leak-check=full ./gofromc
==7974== Memcheck, a memory error detector
==7974== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==7974== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==7974== Command: ./gofromc
==7974==
x: 10.000000, y: 12.000000
==7974==
==7974== HEAP SUMMARY:
==7974== in use at exit: 8 bytes in 1 blocks
==7974== total heap usage: 2 allocs, 1 frees, 1,032 bytes allocated
==7974==
==7974== 8 bytes in 1 blocks are definitely lost in loss record 1 of 1
==7974== at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==7974== by 0x10869B: getPoint (in /home/liz/src/github.com/liztio/cgo-demo/src/gofromc/gofromc)
==7974== by 0x10871C: main (in /home/liz/src/github.com/liztio/cgo-demo/src/gofromc/gofromc)
==7974==
==7974== LEAK SUMMARY:
==7974== definitely lost: 8 bytes in 1 blocks
==7974== indirectly lost: 0 bytes in 0 blocks
==7974== possibly lost: 0 bytes in 0 blocks
==7974== still reachable: 0 bytes in 0 blocks
==7974== suppressed: 0 bytes in 0 blocks
==7974==
==7974== For counts of detected and suppressed errors, rerun with: -v
==7974== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta
What happens if you forget to free?
$ valgrind --leak-check=full ./gofromc
==7974== Memcheck, a memory error detector
==7974== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==7974== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==7974== Command: ./gofromc
==7974==
x: 10.000000, y: 12.000000
==7974==
==7974== HEAP SUMMARY:
==7974== in use at exit: 8 bytes in 1 blocks
==7974== total heap usage: 2 allocs, 1 frees, 1,032 bytes allocated
==7974==
==7974== 8 bytes in 1 blocks are definitely lost in loss record 1 of 1
==7974== at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==7974== by 0x10869B: getPoint (in /home/liz/src/github.com/liztio/cgo-demo/src/gofromc/gofromc)
==7974== by 0x10871C: main (in /home/liz/src/github.com/liztio/cgo-demo/src/gofromc/gofromc)
==7974==
==7974== LEAK SUMMARY:
==7974== definitely lost: 8 bytes in 1 blocks
==7974== indirectly lost: 0 bytes in 0 blocks
==7974== possibly lost: 0 bytes in 0 blocks
==7974== still reachable: 0 bytes in 0 blocks
==7974== suppressed: 0 bytes in 0 blocks
==7974==
==7974== For counts of detected and suppressed errors, rerun with: -v
==7974== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta
What happens if you forget to free?
$ valgrind --leak-check=full ./gofromc
==7974== 8 bytes in 1 blocks are definitely lost in loss record 1 of 1
==7974== at 0x4C2FB0F: malloc (in
/usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==7974== by 0x10869B: getPoint (in
/home/liz/src/github.com/liztio/cgo-demo/src/gofromc/gofromc)
==7974== by 0x10871C: main (in
/home/liz/src/github.com/liztio/cgo-demo/src/gofromc/gofromc)
github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta
Passing Pointers between
C and Go
github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta
Okay
● Passing Go pointers to C
● Passing C pointers to Go
● Storing Go pointers in C memory before
returning
● A bunch of weird special cases involving
Java and Darwin
● Passing Go pointers with nested pointers
to C
● Storing Go pointers in Go memory from C
● Storing Go pointers in C memory
● Storing Go pointers in C memory after
returning
● Go Functions called by C returning Go
pointers
Invalid
github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta
tl;dr
● Pass pointers carefully
● Read the Cgo docs (golang.org/cmd/cgo)
github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta
How about something
nontrivial?
github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta
How about a little magick?
github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta
#include <wand/magick_wand.h>
int main() {
MagickWand *mw = NULL;
MagickWandGenesis();
/* Create a wand */
mw = NewMagickWand();
/* Read the input image */
MagickReadImage(mw,"logo:");
/* write it */
MagickWriteImage(mw,"logo.jpg");
/* Tidy up */
if(mw) mw = DestroyMagickWand(mw);
MagickWandTerminus();
}
https://imagemagick.org/MagickWand/
github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta
package main
// #cgo pkg-config: MagickWand
// #include <wand/MagickWand.h>
import "C"
func main() {
C.MagickWandGenesis()
/* Create a wand */
mw := C.NewMagickWand()
defer func() {
/* Tidy up */
C.DestroyMagickWand(mw)
C.MagickWandTerminus()
}()
/* Read the input image */
C.MagickReadImage(mw, C.CString("logo:"))
/* write it */
C.MagickWriteImage(mw,
C.CString("logo.jpg"))
}
github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta
what’s this?
// #cgo pkg-config: MagickWand
github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta
$ pkg-config MagickWand --cflags
-fopenmp -DMAGICKCORE_HDRI_ENABLE=0 -DMAGICKCORE_QUANTUM_DEPTH=16 -fopenmp -DMAGICKCORE_
$ pkg-config MagickWand --libs
-lMagickWand-6.Q16 -lMagickCore-6.Q16
github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta
Expands to
// #cgo CFLAGS: -I/usr/include/ImageMagick-6 -I/usr/include/x86_64-linux-gnu/ImageMagick-6
// #cgo LDFLAGS: -lMagickWand-6.Q16 -lMagickCore-6.Q16
github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta
C defer anyone?
defer func() {
/* Tidy up */
C.DestroyMagickWand(mw)
C.MagickWandTerminus()
}()
github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta
Full resizing demo in the Github Repo!
github.com/liztio/cgo-demo/cmd/imagemagick
github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta
Dynamic Libraries
github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta
“Go binaries are
static”
github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta
Windows OSX Linux
.dll .dylib .so
github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta
int localFunc() {
return 0;
}
int main() {
return localFunc();
}
github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta
main 0x0000000000000605
localFunction 0x00000000000005fa
mybinary
int localFunc() {
return 0;
}
int main() {
return localFunc();
}
github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta
#include <lib1.h>
#include <lib2.h>
void localFunction() {
char *str = lib1Func1();
lib2Func2(str);
}
int main() {
localFunction()
}
github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta
main.main 0x00000000004891d0
localFunction 0x0000000000489985
lib1func1
lib2func2
mybinary
#include <lib1.h>
#include <lib2.h>
void localFunction() {
char *str = lib1Func1();
lib2Func2(str);
}
int main() {
localFunction()
}
github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta
main.main 0x00000000004891d0
localFunction 0x0000000000489985
lib1func1
lib2func2
lib1func0 0x00000000004891d0
lib1func1 0x0000000000489985
lib1func2 0x0000000000489985
lib2func0 0x0000000000455ea0
lib2func1 0x000000000073f598
lib2func2 0x000000000073f598
lib1.so
lib2.so
mybinary
github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta
LDD(1) Linux Programmer's Manual LDD(1)
NAME
ldd - print shared object dependencies
SYNOPSIS
ldd [option]... file...
github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta
$ ldd ~/bin/ginkgo
linux-vdso.so.1 (0x00007ffc71493000)
libpthread.so.0 =>
/lib/x86_64-linux-gnu/libpthread.so.0
(0x00007fa2d36c4000)
libc.so.6 =>
/lib/x86_64-linux-gnu/libc.so.6
(0x00007fa2d32d3000)
/lib64/ld-linux-x86-64.so.2
(0x00007fa2d38e3000)
github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta
$ ldd ~/bin/ginkgo
linux-vdso.so.1 (0x00007ffc71493000)
libpthread.so.0 =>
/lib/x86_64-linux-gnu/libpthread.so.0
(0x00007fa2d36c4000)
libc.so.6 =>
/lib/x86_64-linux-gnu/libc.so.6
(0x00007fa2d32d3000)
/lib64/ld-linux-x86-64.so.2
(0x00007fa2d38e3000)
github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta
// #cgo LDFLAGS: -laddlib
// #include "addlib.h"
import "C"
github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta
$ go install github.com/liztio/cgo-demo/cmd/addbin
github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta
$ export ADDLIB_DIR=/home/liz/src/github.com/liztio/cgo-demo/src/addlib
$ export CGO_CFLAGS=-I$ADDLIB_DIR
$ export CGO_LDFLAGS=-L$ADDLIB_DIR
$ go install github.com/liztio/cgo-demo/cmd/addbin
github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta
$ export ADDLIB_DIR=/home/liz/src/github.com/liztio/cgo-demo/src/addlib
$ export CGO_CFLAGS=-I$ADDLIB_DIR
$ export CGO_LDFLAGS=-L$ADDLIB_DIR
$ go install github.com/liztio/cgo-demo/cmd/addbin
github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta
$ ldd addbin
linux-vdso.so.1 (0x00007ffd2b966000)
libaddlib.so => not found
libpthread.so.0 =>
/lib/x86_64-linux-gnu/libpthread.so.0
(0x00007f252a003000)
libc.so.6 =>
/lib/x86_64-linux-gnu/libc.so.6
(0x00007f2529c12000)
/lib64/ld-linux-x86-64.so.2
(0x00007f252a222000)
github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta
$ ldd addbin
linux-vdso.so.1 (0x00007ffd2b966000)
libaddlib.so => not found
libpthread.so.0 =>
/lib/x86_64-linux-gnu/libpthread.so.0
(0x00007f252a003000)
libc.so.6 =>
/lib/x86_64-linux-gnu/libc.so.6
(0x00007f2529c12000)
/lib64/ld-linux-x86-64.so.2
(0x00007f252a222000)
github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta
$ addbin
addbin: error while loading shared libraries:
libaddlib.so: cannot open shared object file:
No such file or directory
github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta
$ LD_LIBRARY_PATH=$ADDLIB_DIR addbin
Go says: 11 + one is 12
github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta
Questions?
Please play with the code!
github.com/liztio/cgo-demo
1 of 86

Recommended

[GSoC 2017] gopy: Updating gopy to support Python3 and PyPy by
[GSoC 2017] gopy: Updating gopy to support Python3 and PyPy[GSoC 2017] gopy: Updating gopy to support Python3 and PyPy
[GSoC 2017] gopy: Updating gopy to support Python3 and PyPyDong-hee Na
216 views20 slides
Python分享 by
Python分享Python分享
Python分享fangdeng
313 views43 slides
Mixing C++ & Python II: Pybind11 by
Mixing C++ & Python II: Pybind11Mixing C++ & Python II: Pybind11
Mixing C++ & Python II: Pybind11corehard_by
4.3K views59 slides
How to master C++ by
How to master C++How to master C++
How to master C++Florian Richoux
1.6K views73 slides
David Mertz. Type Annotations. PyCon Belarus 2015 by
David Mertz. Type Annotations. PyCon Belarus 2015David Mertz. Type Annotations. PyCon Belarus 2015
David Mertz. Type Annotations. PyCon Belarus 2015Alina Dolgikh
1.4K views42 slides
Go introduction by
Go   introductionGo   introduction
Go introductionAnna Goławska
162 views54 slides

More Related Content

Similar to CGo for fun and profit

Understanding Pseudo-Versions Moving to Go 1.13 What is in Go 1.14+ for Modules by
Understanding Pseudo-Versions Moving to Go 1.13 What is in Go 1.14+ for ModulesUnderstanding Pseudo-Versions Moving to Go 1.13 What is in Go 1.14+ for Modules
Understanding Pseudo-Versions Moving to Go 1.13 What is in Go 1.14+ for ModulesMitali Bisht
176 views18 slides
Pseudo-versions, moving to Go1.13 and later versions by
Pseudo-versions, moving to Go1.13 and later versionsPseudo-versions, moving to Go1.13 and later versions
Pseudo-versions, moving to Go1.13 and later versionsMitali Bisht
129 views18 slides
Hacking the Codename One Source Code - Part I.pdf by
Hacking the Codename One Source Code - Part I.pdfHacking the Codename One Source Code - Part I.pdf
Hacking the Codename One Source Code - Part I.pdfShaiAlmog1
294 views7 slides
Evolution and AI by
Evolution and AIEvolution and AI
Evolution and AIMiyoshi Kosuke
227 views50 slides
Eta lang Beauty And The Beast by
Eta lang Beauty And The Beast Eta lang Beauty And The Beast
Eta lang Beauty And The Beast Jarek Ratajski
228 views113 slides
나도 할 수 있다 오픈소스 by
나도 할 수 있다 오픈소스나도 할 수 있다 오픈소스
나도 할 수 있다 오픈소스효준 강
704 views54 slides

Similar to CGo for fun and profit(20)

Understanding Pseudo-Versions Moving to Go 1.13 What is in Go 1.14+ for Modules by Mitali Bisht
Understanding Pseudo-Versions Moving to Go 1.13 What is in Go 1.14+ for ModulesUnderstanding Pseudo-Versions Moving to Go 1.13 What is in Go 1.14+ for Modules
Understanding Pseudo-Versions Moving to Go 1.13 What is in Go 1.14+ for Modules
Mitali Bisht176 views
Pseudo-versions, moving to Go1.13 and later versions by Mitali Bisht
Pseudo-versions, moving to Go1.13 and later versionsPseudo-versions, moving to Go1.13 and later versions
Pseudo-versions, moving to Go1.13 and later versions
Mitali Bisht129 views
Hacking the Codename One Source Code - Part I.pdf by ShaiAlmog1
Hacking the Codename One Source Code - Part I.pdfHacking the Codename One Source Code - Part I.pdf
Hacking the Codename One Source Code - Part I.pdf
ShaiAlmog1294 views
Eta lang Beauty And The Beast by Jarek Ratajski
Eta lang Beauty And The Beast Eta lang Beauty And The Beast
Eta lang Beauty And The Beast
Jarek Ratajski228 views
나도 할 수 있다 오픈소스 by 효준 강
나도 할 수 있다 오픈소스나도 할 수 있다 오픈소스
나도 할 수 있다 오픈소스
효준 강704 views
Goの標準的な開発の流れ by Ryuji Iwata
Goの標準的な開発の流れGoの標準的な開発の流れ
Goの標準的な開発の流れ
Ryuji Iwata449 views
Golang 101 for IT-Pros - Cisco Live Orlando 2018 - DEVNET-1808 by Cisco DevNet
Golang 101 for IT-Pros - Cisco Live Orlando 2018 - DEVNET-1808Golang 101 for IT-Pros - Cisco Live Orlando 2018 - DEVNET-1808
Golang 101 for IT-Pros - Cisco Live Orlando 2018 - DEVNET-1808
Cisco DevNet219 views
JAZOON'13 - Thomas Hug & Bartosz Majsak - Git Workshop -Essentials by jazoon13
JAZOON'13 - Thomas Hug & Bartosz Majsak - Git Workshop -EssentialsJAZOON'13 - Thomas Hug & Bartosz Majsak - Git Workshop -Essentials
JAZOON'13 - Thomas Hug & Bartosz Majsak - Git Workshop -Essentials
jazoon133.3K views
You got database in my cloud! by Liz Frost
You got database  in my cloud!You got database  in my cloud!
You got database in my cloud!
Liz Frost207 views
Git workflows presentation by Mack Hardy
Git workflows presentationGit workflows presentation
Git workflows presentation
Mack Hardy2.7K views
Git single branch by Carl Brown
Git single branchGit single branch
Git single branch
Carl Brown1.3K views
Develop Android app using Golang by SeongJae Park
Develop Android app using GolangDevelop Android app using Golang
Develop Android app using Golang
SeongJae Park37.2K views

Recently uploaded

NEW SUPPLIERS SUPPLIES (copie).pdf by
NEW SUPPLIERS SUPPLIES (copie).pdfNEW SUPPLIERS SUPPLIES (copie).pdf
NEW SUPPLIERS SUPPLIES (copie).pdfgeorgesradjou
14 views30 slides
Saikat Chakraborty Java Oracle Certificate.pdf by
Saikat Chakraborty Java Oracle Certificate.pdfSaikat Chakraborty Java Oracle Certificate.pdf
Saikat Chakraborty Java Oracle Certificate.pdfSaikatChakraborty787148
14 views1 slide
cloud computing-virtualization.pptx by
cloud computing-virtualization.pptxcloud computing-virtualization.pptx
cloud computing-virtualization.pptxRajaulKarim20
85 views31 slides
Informed search algorithms.pptx by
Informed search algorithms.pptxInformed search algorithms.pptx
Informed search algorithms.pptxDr.Shweta
13 views19 slides
SWM L1-L14_drhasan (Part 1).pdf by
SWM L1-L14_drhasan (Part 1).pdfSWM L1-L14_drhasan (Part 1).pdf
SWM L1-L14_drhasan (Part 1).pdfMahmudHasan747870
48 views150 slides
9_DVD_Dynamic_logic_circuits.pdf by
9_DVD_Dynamic_logic_circuits.pdf9_DVD_Dynamic_logic_circuits.pdf
9_DVD_Dynamic_logic_circuits.pdfUsha Mehta
28 views32 slides

Recently uploaded(20)

NEW SUPPLIERS SUPPLIES (copie).pdf by georgesradjou
NEW SUPPLIERS SUPPLIES (copie).pdfNEW SUPPLIERS SUPPLIES (copie).pdf
NEW SUPPLIERS SUPPLIES (copie).pdf
georgesradjou14 views
cloud computing-virtualization.pptx by RajaulKarim20
cloud computing-virtualization.pptxcloud computing-virtualization.pptx
cloud computing-virtualization.pptx
RajaulKarim2085 views
Informed search algorithms.pptx by Dr.Shweta
Informed search algorithms.pptxInformed search algorithms.pptx
Informed search algorithms.pptx
Dr.Shweta13 views
9_DVD_Dynamic_logic_circuits.pdf by Usha Mehta
9_DVD_Dynamic_logic_circuits.pdf9_DVD_Dynamic_logic_circuits.pdf
9_DVD_Dynamic_logic_circuits.pdf
Usha Mehta28 views
Thermal aware task assignment for multicore processors using genetic algorithm by IJECEIAES
Thermal aware task assignment for multicore processors using genetic algorithm Thermal aware task assignment for multicore processors using genetic algorithm
Thermal aware task assignment for multicore processors using genetic algorithm
IJECEIAES30 views
STUDY OF SMART MATERIALS USED IN CONSTRUCTION-1.pptx by AnnieRachelJohn
STUDY OF SMART MATERIALS USED IN CONSTRUCTION-1.pptxSTUDY OF SMART MATERIALS USED IN CONSTRUCTION-1.pptx
STUDY OF SMART MATERIALS USED IN CONSTRUCTION-1.pptx
AnnieRachelJohn31 views
A multi-microcontroller-based hardware for deploying Tiny machine learning mo... by IJECEIAES
A multi-microcontroller-based hardware for deploying Tiny machine learning mo...A multi-microcontroller-based hardware for deploying Tiny machine learning mo...
A multi-microcontroller-based hardware for deploying Tiny machine learning mo...
IJECEIAES12 views
13_DVD_Latch-up_prevention.pdf by Usha Mehta
13_DVD_Latch-up_prevention.pdf13_DVD_Latch-up_prevention.pdf
13_DVD_Latch-up_prevention.pdf
Usha Mehta10 views
Performance of Back-to-Back Mechanically Stabilized Earth Walls Supporting th... by ahmedmesaiaoun
Performance of Back-to-Back Mechanically Stabilized Earth Walls Supporting th...Performance of Back-to-Back Mechanically Stabilized Earth Walls Supporting th...
Performance of Back-to-Back Mechanically Stabilized Earth Walls Supporting th...
ahmedmesaiaoun12 views
Machine Element II Course outline.pdf by odatadese1
Machine Element II Course outline.pdfMachine Element II Course outline.pdf
Machine Element II Course outline.pdf
odatadese17 views

CGo for fun and profit

  • 1. github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta Foreign Functions for Fun and Profit When and how to use CGo
  • 2. github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta github.com/liztio/cgo-demo
  • 5. github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta @stillinbeta
  • 7. github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta recurse.com
  • 8. github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta Renee French. (http://reneefrench.blogspot.com/)
  • 9. github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta Full disclosure? ...I don’t actually like Go very much.
  • 10. github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta but I use it a lot
  • 11. github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta Why not Cgo?
  • 12. github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta cgo is not Go - Dave Cheney bit.ly/cgo-not-go
  • 13. github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta Why not Cgo ● More complicated compilation ● Less portable ● No cross compilation ● More segfaults ● No backtraces ● Less tooling
  • 14. github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta Why Cgo ● ...sometimes it’s the only way
  • 15. github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta Calling C from Go
  • 16. github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta #include <stdint.h> uint32_t add_one(uint32_t val); addlib.h #include "addlib.h" uint32_t add_one(uint32_t val) { return val + 1; } addlib.c
  • 17. github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta uint32_t Unsigned integer 32 bit type
  • 18. github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta import "C"
  • 19. github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta // #include "addlib.h" import "C"
  • 20. github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta added := C.add_one(num)
  • 21. github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta main.go package main // #include "addlib.h" import "C" // “C” always gets its own line import "fmt" func main() { num := 10 added := C.add_one(num) fmt.Printf("%d + 1 is %d!n", num, added) }
  • 22. github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta $ go run github.com/liztio/cgo-demo/cmd/c_from_go
  • 23. github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta $ go run github.com/liztio/cgo-demo/cmd/c_from_go # github.com/liztio/cgo-demo/cmd/c_from_go cmd/c_from_go/main.go:10:27: cannot use num (type int) as type _Ctype_uint in argument to _Cfunc_add_one
  • 24. github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta added := C.add_one(C.uint32_t(num))
  • 25. github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta $ go run github.com/liztio/cgo-demo/cmd/c_from_go 10 + 1 is 11!
  • 26. github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta Calling Go from C
  • 27. github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta //export Greet func Greet(chars *C.char) { str := C.GoString(chars) fmt.Printf("Hello from Go, %s!n", str) }
  • 28. github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta //export Greet func Greet(chars *C.char) { str := C.GoString(chars) fmt.Printf("Hello from Go, %s!n", str) }
  • 29. github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta //export Greet func Greet(chars *C.char) { str := C.GoString(chars) fmt.Printf("Hello from Go, %s!n", str) }
  • 30. github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta F O S D E M x00 Strings in C
  • 31. github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta F O S D E M x00 46 4F 53 44 45 4d 00 Strings in C
  • 32. github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta F O S D E M *ptr 6 Strings in Go
  • 33. github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta //export Greet func Greet(chars *C.char) { str := C.GoString(chars) fmt.Printf("Hello from Go, %s!n", str) }
  • 34. github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta package main import "C" import "fmt" //export Greet func Greet(chars *C.char) { str := C.GoString(chars) fmt.Printf("Hello from Go, %s!n", str) } func main() {} // required for main package greet.go
  • 35. github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta main.c #include "_cgo_export.h" int main() { char *name = "FOSDEM"; Greet(name); return 0; // exit code }
  • 36. github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta _cgo_export.h /* Code generated by cmd/cgo; DO NOT EDIT. */ /* package main */ #line 1 "cgo-builtin-prolog" #include <stddef.h> /* for ptrdiff_t below */ #ifndef GO_CGO_EXPORT_PROLOGUE_H #define GO_CGO_EXPORT_PROLOGUE_H typedef struct { const char *p; ptrdiff_t n; } _GoString_; #endif /* Start of preamble from import "C" comments. */ /* End of preamble from import "C" comments. */ /* Start of boilerplate cgo prologue. */
  • 37. github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta _cgo_export.h /* don't worry about it */
  • 38. github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta A brief introduction to Makefiles
  • 39. github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta A brief introduction to Makefiles all: output output: input1 input2 input3 command --output $@ --inputs $^
  • 40. github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta A brief introduction to Makefiles all: output output: input1 input2 input3 command --output output --inputs input1 input2 input3
  • 41. github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta Our Makefile _cgo_export.h: greet.go go tool cgo -exportheader $@ $^ greet.a: greet.go go build -buildmode=c-archive $^ gofromc: main.c _cgo_export.h greet.a $(CC) -o $@ $^ -lpthread
  • 42. github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta Our Makefile _cgo_export.h: greet.go go tool cgo -exportheader $@ $^
  • 43. github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta Our Makefile greet.a: greet.go go build -buildmode=c-archive $^
  • 44. github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta Our Makefile gofromc: main.c _cgo_export.h greet.a $(CC) -o $@ $^ -lpthread
  • 45. github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta $ make go tool cgo -exportheader _cgo_export.h greet.go go build -buildmode=c-archive greet.go cc -o gofromc main.c _cgo_export.h greet.a -lpthread
  • 46. github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta Let’s try it out! $ ./gofromc Hello from Go, FOSDEM!
  • 47. github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta Pointers and Memory
  • 48. github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta Go Memory ● new() / &value ● Garbage Collected ● malloc() ● Manually Freed with free() C Memory
  • 49. github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta Allocating in Go type Point struct { x, y float32 } func getPoint() *Point { return &Point{ x: 10, y: 12, } } typedef struct { float x; float y; } Point; Point *getPoint() { Point *pt = malloc(sizeof(Point)); pt->x = 10; pt->y = 12; return pt; } Allocating in C
  • 50. github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta Go func usePoint(pt *Point) { fmt.Printf("x: %f, y: %fn", pt.x, pt.y) // Goes out of scope } void usePoint(Point *pt) { printf("x: %f, y: %fn", pt->x, pt->y); free(pt); } C
  • 51. github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta What happens if you forget to free? $ ./gofromc x: 10.000000, y: 12.000000
  • 52. github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta What happens if you forget to free? $ valgrind --leak-check=full ./gofromc ==7974== Memcheck, a memory error detector ==7974== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al. ==7974== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info ==7974== Command: ./gofromc ==7974== x: 10.000000, y: 12.000000 ==7974== ==7974== HEAP SUMMARY: ==7974== in use at exit: 8 bytes in 1 blocks ==7974== total heap usage: 2 allocs, 1 frees, 1,032 bytes allocated ==7974== ==7974== 8 bytes in 1 blocks are definitely lost in loss record 1 of 1 ==7974== at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==7974== by 0x10869B: getPoint (in /home/liz/src/github.com/liztio/cgo-demo/src/gofromc/gofromc) ==7974== by 0x10871C: main (in /home/liz/src/github.com/liztio/cgo-demo/src/gofromc/gofromc) ==7974== ==7974== LEAK SUMMARY: ==7974== definitely lost: 8 bytes in 1 blocks ==7974== indirectly lost: 0 bytes in 0 blocks ==7974== possibly lost: 0 bytes in 0 blocks ==7974== still reachable: 0 bytes in 0 blocks ==7974== suppressed: 0 bytes in 0 blocks ==7974== ==7974== For counts of detected and suppressed errors, rerun with: -v ==7974== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
  • 53. github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta What happens if you forget to free? $ valgrind --leak-check=full ./gofromc ==7974== Memcheck, a memory error detector ==7974== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al. ==7974== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info ==7974== Command: ./gofromc ==7974== x: 10.000000, y: 12.000000 ==7974== ==7974== HEAP SUMMARY: ==7974== in use at exit: 8 bytes in 1 blocks ==7974== total heap usage: 2 allocs, 1 frees, 1,032 bytes allocated ==7974== ==7974== 8 bytes in 1 blocks are definitely lost in loss record 1 of 1 ==7974== at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==7974== by 0x10869B: getPoint (in /home/liz/src/github.com/liztio/cgo-demo/src/gofromc/gofromc) ==7974== by 0x10871C: main (in /home/liz/src/github.com/liztio/cgo-demo/src/gofromc/gofromc) ==7974== ==7974== LEAK SUMMARY: ==7974== definitely lost: 8 bytes in 1 blocks ==7974== indirectly lost: 0 bytes in 0 blocks ==7974== possibly lost: 0 bytes in 0 blocks ==7974== still reachable: 0 bytes in 0 blocks ==7974== suppressed: 0 bytes in 0 blocks ==7974== ==7974== For counts of detected and suppressed errors, rerun with: -v ==7974== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
  • 54. github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta What happens if you forget to free? $ valgrind --leak-check=full ./gofromc ==7974== 8 bytes in 1 blocks are definitely lost in loss record 1 of 1 ==7974== at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==7974== by 0x10869B: getPoint (in /home/liz/src/github.com/liztio/cgo-demo/src/gofromc/gofromc) ==7974== by 0x10871C: main (in /home/liz/src/github.com/liztio/cgo-demo/src/gofromc/gofromc)
  • 55. github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta Passing Pointers between C and Go
  • 56. github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta Okay ● Passing Go pointers to C ● Passing C pointers to Go ● Storing Go pointers in C memory before returning ● A bunch of weird special cases involving Java and Darwin ● Passing Go pointers with nested pointers to C ● Storing Go pointers in Go memory from C ● Storing Go pointers in C memory ● Storing Go pointers in C memory after returning ● Go Functions called by C returning Go pointers Invalid
  • 57. github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta tl;dr ● Pass pointers carefully ● Read the Cgo docs (golang.org/cmd/cgo)
  • 58. github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta How about something nontrivial?
  • 59. github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta How about a little magick?
  • 60. github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta #include <wand/magick_wand.h> int main() { MagickWand *mw = NULL; MagickWandGenesis(); /* Create a wand */ mw = NewMagickWand(); /* Read the input image */ MagickReadImage(mw,"logo:"); /* write it */ MagickWriteImage(mw,"logo.jpg"); /* Tidy up */ if(mw) mw = DestroyMagickWand(mw); MagickWandTerminus(); } https://imagemagick.org/MagickWand/
  • 61. github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta package main // #cgo pkg-config: MagickWand // #include <wand/MagickWand.h> import "C" func main() { C.MagickWandGenesis() /* Create a wand */ mw := C.NewMagickWand() defer func() { /* Tidy up */ C.DestroyMagickWand(mw) C.MagickWandTerminus() }() /* Read the input image */ C.MagickReadImage(mw, C.CString("logo:")) /* write it */ C.MagickWriteImage(mw, C.CString("logo.jpg")) }
  • 62. github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta what’s this? // #cgo pkg-config: MagickWand
  • 63. github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta $ pkg-config MagickWand --cflags -fopenmp -DMAGICKCORE_HDRI_ENABLE=0 -DMAGICKCORE_QUANTUM_DEPTH=16 -fopenmp -DMAGICKCORE_ $ pkg-config MagickWand --libs -lMagickWand-6.Q16 -lMagickCore-6.Q16
  • 64. github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta Expands to // #cgo CFLAGS: -I/usr/include/ImageMagick-6 -I/usr/include/x86_64-linux-gnu/ImageMagick-6 // #cgo LDFLAGS: -lMagickWand-6.Q16 -lMagickCore-6.Q16
  • 65. github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta C defer anyone? defer func() { /* Tidy up */ C.DestroyMagickWand(mw) C.MagickWandTerminus() }()
  • 66. github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta Full resizing demo in the Github Repo! github.com/liztio/cgo-demo/cmd/imagemagick
  • 67. github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta Dynamic Libraries
  • 68. github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta “Go binaries are static”
  • 69. github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta Windows OSX Linux .dll .dylib .so
  • 70. github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta int localFunc() { return 0; } int main() { return localFunc(); }
  • 71. github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta main 0x0000000000000605 localFunction 0x00000000000005fa mybinary int localFunc() { return 0; } int main() { return localFunc(); }
  • 72. github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta #include <lib1.h> #include <lib2.h> void localFunction() { char *str = lib1Func1(); lib2Func2(str); } int main() { localFunction() }
  • 73. github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta main.main 0x00000000004891d0 localFunction 0x0000000000489985 lib1func1 lib2func2 mybinary #include <lib1.h> #include <lib2.h> void localFunction() { char *str = lib1Func1(); lib2Func2(str); } int main() { localFunction() }
  • 74. github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta main.main 0x00000000004891d0 localFunction 0x0000000000489985 lib1func1 lib2func2 lib1func0 0x00000000004891d0 lib1func1 0x0000000000489985 lib1func2 0x0000000000489985 lib2func0 0x0000000000455ea0 lib2func1 0x000000000073f598 lib2func2 0x000000000073f598 lib1.so lib2.so mybinary
  • 75. github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta LDD(1) Linux Programmer's Manual LDD(1) NAME ldd - print shared object dependencies SYNOPSIS ldd [option]... file...
  • 76. github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta $ ldd ~/bin/ginkgo linux-vdso.so.1 (0x00007ffc71493000) libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fa2d36c4000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fa2d32d3000) /lib64/ld-linux-x86-64.so.2 (0x00007fa2d38e3000)
  • 77. github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta $ ldd ~/bin/ginkgo linux-vdso.so.1 (0x00007ffc71493000) libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fa2d36c4000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fa2d32d3000) /lib64/ld-linux-x86-64.so.2 (0x00007fa2d38e3000)
  • 78. github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta // #cgo LDFLAGS: -laddlib // #include "addlib.h" import "C"
  • 79. github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta $ go install github.com/liztio/cgo-demo/cmd/addbin
  • 80. github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta $ export ADDLIB_DIR=/home/liz/src/github.com/liztio/cgo-demo/src/addlib $ export CGO_CFLAGS=-I$ADDLIB_DIR $ export CGO_LDFLAGS=-L$ADDLIB_DIR $ go install github.com/liztio/cgo-demo/cmd/addbin
  • 81. github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta $ export ADDLIB_DIR=/home/liz/src/github.com/liztio/cgo-demo/src/addlib $ export CGO_CFLAGS=-I$ADDLIB_DIR $ export CGO_LDFLAGS=-L$ADDLIB_DIR $ go install github.com/liztio/cgo-demo/cmd/addbin
  • 82. github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta $ ldd addbin linux-vdso.so.1 (0x00007ffd2b966000) libaddlib.so => not found libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f252a003000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f2529c12000) /lib64/ld-linux-x86-64.so.2 (0x00007f252a222000)
  • 83. github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta $ ldd addbin linux-vdso.so.1 (0x00007ffd2b966000) libaddlib.so => not found libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f252a003000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f2529c12000) /lib64/ld-linux-x86-64.so.2 (0x00007f252a222000)
  • 84. github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta $ addbin addbin: error while loading shared libraries: libaddlib.so: cannot open shared object file: No such file or directory
  • 85. github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta $ LD_LIBRARY_PATH=$ADDLIB_DIR addbin Go says: 11 + one is 12
  • 86. github.com/liztio/cgo-demo // #FOSDEM 2019 // @stillinbeta Questions? Please play with the code! github.com/liztio/cgo-demo