You cannot use a cgo shared library in a Go program, because you cannot have multiple Go runtimes in the same process.
Trying to do so will give the error:
# command-line-arguments
cgo-gcc-prolog:67:33: warning: unused variable '_cgo_a' [-Wunused-variable]
fatal error: unexpected signal during runtime execution
[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x43fd5e2]
goroutine 1 [running, locked to thread]:
runtime.throw({0x40a875b?, 0x1c00011b800?})
/usr/local/go/src/runtime/panic.go:992 +0x71 fp=0x1c00004a960 sp=0x1c00004a930 pc=0x402f6d1
runtime: unexpected return pc for runtime.sigpanic called from 0x43fd5e2
stack: frame={sp:0x1c00004a960, fp:0x1c00004a9b0} stack=[0x1c00004a000,0x1c00004b000)
....
0x000001c00004aaa0: 0x0000000000000000 0x0000000000000000
runtime.sigpanic()
/usr/local/go/src/runtime/signal_unix.go:781 +0x3a9 fp=0x1c00004a9b0 sp=0x1c00004a960 pc=0x4043449
exit status 2
To call c code from go, there are 3 potential approaches:
- Inline coding, as:
package main
//#include <stdio.h>
//int Add(int a, int b){
// printf("Welcome from external C function\n");
// return a + b;
//}
import "C"
import "fmt"
func main() {
fmt.Println(C.Add(5, 2))
}
- Static linking, where you have both
.c
and .h
files, as:
// lib.c
#include <stdio.h>
int Add(int a, int b){
printf("Welcome from external C function\n");
return a + b;
}
And
// libadd.h
int Add(int, int);
And the go file be:
// main.go
package main
// #include "libadd.h"
import "C"
import "fmt"
func main() {
x := C.Add(1, 2)
fmt.Println(x)
}
We have to run the file as go run .
or go run github.io/xxx
// go run main.go will not work as it will consider main.go only, and not consider the C file
- Dynamic linking, where you compile the above
c
file as clang -shared -fpic -Wall -g lib.c -o libadd.so
and have the go file as:
// main.go
package main
//#cgo CFLAGS: -g -Wall
//#cgo LDFLAGS: -L. -ladd
//#include "libadd.h"
import "C"
import "fmt"
func main() {
x := C.Add(1, 2)
fmt.Println(x)
}
Here you can use go run main.go
as the librry is connected through the hard code, to disctrubute the binary, the shared library loadadd.so
is required to be distrubuted with the same binary file and existing in the same folder.
I uploaded seperate folders for each case [here][1]
BONUS
To call the generated share library in go using a c program, we can use the below:
// main.c
#include <stdio.h>
#include "libadd.h" // calling C file
#include "libgo.h" // calling shared library generated by GO
int main()
{
HelloWorld();
int x = Add(1, 2);
printf("%d",x);
return 0;
}
Compiling the file as:
``bash
clang -o main -L. -ladd -lgo main.c // -ladd => -l (library) is libadd
[1]: https://github.com/hajsf/tutorial/tree/master/ffi