The Go tools are capable of static and dynamic linking with other libraries, and also there is possbility to create static and dynamic library, therefore it is possible to create a bridge between golang and the other language both ways.
Let’s create library we will use in external systems. Here is an example. File example.go
:
package main
import "C"
import "fmt"
//export SayHello
func SayHello(hello *C.char) {
fmt.Print(C.GoString(hello))
}
func main() {}
and Makefile
that will contain build script that you can invoke by make static
or make shared
. I am not sure if my solution present shows a good practice. Feel free to send a PR with improvement.
static example.a:
go build -o example.a -buildmode=c-archive example.go
shared example.dylib:
go build -o example.dylib -buildmode=c-shared example.go
As far as I understand the main function is neccecery to include into library, because the final product has to have for example GC rutines. The comment starting from //export {function name}
tells the comiler that this the function will be called from the outside.
First off we will create C++ library that we will use in out Go program.
File example.cxx
:
#include <stdio.h>
extern "C" {
void PrintHello(const char* u) {
printf("Hello: %s\n", u);
}
}
And example.hxx
:
#pragma once
void PrintHello(const char* u)
extern "C" {}
informs the compiler that we want the function names to be preserved. That is, to not “mangle” the names as is done for C++ code.
Makefile
:
static example.a:
clang++ -c -Wall -o lib.o ./example.cxx
ar rc ./libexample.a ./lib.o
shared example.dylib:
clang++ -dynamiclib -o libexample.dylib example.cxx
package main
// #cgo CFLAGS: -I.
// #cgo LDFLAGS: -L. -lexample
//
// #include <example.hxx>
import "C"
func main() {
C.PrintHello(C.CString("Hello Golang"))
}
The program is linked staticaly with libexample when you build it.
gem install ffi
require 'ffi'
module Example
extend FFI::Library
ffi_lib './example.dylib'
attach_function :SayHello, [:string]
end
Example.SayHello("Hello")
More informations about FFI: https://en.wikipedia.org/wiki/Foreign_function_interface
import ctypes
libc = ctypes.CDLL('./example.dylib')
libc.SayHello("Hello")