Let's call some Go code from C! Why? Because I'm too lazy^Wdumb to write robust enough network code with tls and requests pool using C.
First, we need to make Go's symbols exportable,
pay attention to import "C"
and //export Name
(no space!):
package main
import "C"
//export Echo
func Echo(s string) {
log.Printf("go: echo: %q", s)
}
//export Ints
func Ints(is []int) {
log.Printf("go: ints: got %d values %v", len(is), is)
}
//export Strings
func Strings(ss []string) {
log.Printf("go: strings: %s", strings.Join(ss, ", "))
}
// we need an empty main in package main.
func main() {}
Then, build this module as shared library:
CGO_ENABLED=1 go build -o libwtf.so -buildmode=c-shared .
You'll get libwtf.so
and libwtf.h
. The header file contains all exportable types and functions from Go code.
Now we can these functions from C:
// Go's exportable symbols are defined in libwtf.h
#include "libwtf.h"
#include <stdio.h>
#include <string.h>
int main() {
// pass C strings into Go:
char *c = "this is a C string\0";
GoString gs = {.p = c, .n = strlen(c)};
Echo(gs);
// build and use Go's []int:
GoInt numbers[5] = {42, 13, 8, 1989, 0};
GoSlice intSlice = {.data = numbers, .len = 5, .cap = 5};
Ints(intSlice);
// build and use Go's []string
char *strings_to_pass[3] = {
"foo",
"barrr",
"lorem ipsum dolor sit amet",
};
// build slice of Go strings from an array of C strings:
GoString goStrings[3] = {};
for (int i = 0; i < 3; i++) {
goStrings[i].p = strings_to_pass[i];
goStrings[i].n = strlen(strings_to_pass[i]);
}
GoSlice strSlice = {.data = goStrings, .len = 3, .cap = 3};
Strings(strSlice);
}
Fat pointers... do you feel it?
Finally, we need to link against our "libwtf":
cc -o main_c -lwtf -L./ -I./ main.c
Options explanation:
-I
tells CC to look for includes (our "libwtf.h") in a current directory.
-L
tells linker to look for object (our "libwtf.so") in a current directory.
-lwtf
(which is lowercase L followed by wtf) specifies the lib to link against, without the "lib" prefix and ".so" suffix.
This repo contains a lot of Go FFI examples for popular languages.
An example of calling Go code from Python.