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

More Related Content

PDF
[GSoC 2017] gopy: Updating gopy to support Python3 and PyPy
PPTX
Python分享
PPTX
Mixing C++ & Python II: Pybind11
PDF
How to master C++
PDF
David Mertz. Type Annotations. PyCon Belarus 2015
PDF
Go introduction
DOCX
Pslb lab manual
PDF
Take advantage of C++ from Python
[GSoC 2017] gopy: Updating gopy to support Python3 and PyPy
Python分享
Mixing C++ & Python II: Pybind11
How to master C++
David Mertz. Type Annotations. PyCon Belarus 2015
Go introduction
Pslb lab manual
Take advantage of C++ from Python

Similar to CGo for fun and profit (20)

PDF
Something about Golang
PDF
Hidden Dragons of CGO
PDF
Go vs C++ - CppRussia 2019 Piter BoF
PDF
Implementing Software Machines in C and Go
PDF
cgo and Go plugins
PDF
Golang and Eco-System Introduction / Overview
PPTX
golang_getting_started.pptx
PDF
Golang
PDF
Go Lang Tutorial
PPTX
Go Programming Language (Golang)
PDF
Let's Go-lang
PDF
How to avoid Go gotchas - Ivan Daniluk - Codemotion Milan 2016
PDF
Go Says WAT?
PDF
Go Java, Go!
KEY
Beauty and Power of Go
PDF
10〜30分で何となく分かるGo
PPTX
Golang basics for Java developers - Part 1
PDF
golang_refcard.pdf
PPTX
Next Generation Language Go
PDF
Go serving: Building server app with go
Something about Golang
Hidden Dragons of CGO
Go vs C++ - CppRussia 2019 Piter BoF
Implementing Software Machines in C and Go
cgo and Go plugins
Golang and Eco-System Introduction / Overview
golang_getting_started.pptx
Golang
Go Lang Tutorial
Go Programming Language (Golang)
Let's Go-lang
How to avoid Go gotchas - Ivan Daniluk - Codemotion Milan 2016
Go Says WAT?
Go Java, Go!
Beauty and Power of Go
10〜30分で何となく分かるGo
Golang basics for Java developers - Part 1
golang_refcard.pdf
Next Generation Language Go
Go serving: Building server app with go
Ad

More from Liz Frost (6)

PDF
EZRust: Z80 for the Web
PDF
Kubernetes from a Box Mix
PDF
You got database in my cloud!
PDF
Postgres plays pokemon
PDF
Kubeadm Deep Dive (Kubecon Seattle 2018)
PDF
You got database in my cloud (short version)
EZRust: Z80 for the Web
Kubernetes from a Box Mix
You got database in my cloud!
Postgres plays pokemon
Kubeadm Deep Dive (Kubecon Seattle 2018)
You got database in my cloud (short version)
Ad

Recently uploaded (20)

PDF
Influence of Green Infrastructure on Residents’ Endorsement of the New Ecolog...
PPTX
Module 8- Technological and Communication Skills.pptx
PDF
Soil Improvement Techniques Note - Rabbi
PDF
Introduction to Power System StabilityPS
PDF
Computer System Architecture 3rd Edition-M Morris Mano.pdf
PPTX
Management Information system : MIS-e-Business Systems.pptx
PPT
Chapter 1 - Introduction to Manufacturing Technology_2.ppt
PPTX
Graph Data Structures with Types, Traversals, Connectivity, and Real-Life App...
PDF
Applications of Equal_Area_Criterion.pdf
PDF
Unit1 - AIML Chapter 1 concept and ethics
PDF
UEFA_Carbon_Footprint_Calculator_Methology_2.0.pdf
PDF
distributed database system" (DDBS) is often used to refer to both the distri...
PPTX
CyberSecurity Mobile and Wireless Devices
PPTX
CONTRACTS IN CONSTRUCTION PROJECTS: TYPES
PPTX
A Brief Introduction to IoT- Smart Objects: The "Things" in IoT
PPTX
ASME PCC-02 TRAINING -DESKTOP-NLE5HNP.pptx
PPTX
"Array and Linked List in Data Structures with Types, Operations, Implementat...
PPTX
tack Data Structure with Array and Linked List Implementation, Push and Pop O...
PDF
Prof. Dr. KAYIHURA A. SILAS MUNYANEZA, PhD..pdf
PPTX
Principal presentation for NAAC (1).pptx
Influence of Green Infrastructure on Residents’ Endorsement of the New Ecolog...
Module 8- Technological and Communication Skills.pptx
Soil Improvement Techniques Note - Rabbi
Introduction to Power System StabilityPS
Computer System Architecture 3rd Edition-M Morris Mano.pdf
Management Information system : MIS-e-Business Systems.pptx
Chapter 1 - Introduction to Manufacturing Technology_2.ppt
Graph Data Structures with Types, Traversals, Connectivity, and Real-Life App...
Applications of Equal_Area_Criterion.pdf
Unit1 - AIML Chapter 1 concept and ethics
UEFA_Carbon_Footprint_Calculator_Methology_2.0.pdf
distributed database system" (DDBS) is often used to refer to both the distri...
CyberSecurity Mobile and Wireless Devices
CONTRACTS IN CONSTRUCTION PROJECTS: TYPES
A Brief Introduction to IoT- Smart Objects: The "Things" in IoT
ASME PCC-02 TRAINING -DESKTOP-NLE5HNP.pptx
"Array and Linked List in Data Structures with Types, Operations, Implementat...
tack Data Structure with Array and Linked List Implementation, Push and Pop O...
Prof. Dr. KAYIHURA A. SILAS MUNYANEZA, PhD..pdf
Principal presentation for NAAC (1).pptx

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