Golang Works with Shared Object Through cgo (.so Not Found Issue)
Faced the problem with Golang and cgo for a couple days, so just take a quick note to record what had happened.
Shortcut: Jump to [Key Point], [Solution] section
A quick look in [Gist]
From the beginning, my goal was aim to make Golang works with a shared object file (.so) built from a C code.
Just like others in 2023, I went to ChatGPT for an answer which can help me have a quick look for the solution how to achieve the goal.
Key Point
Noticed from Ref[2]: (the reference is written in Chinese)
1. The `.so` file built from gcc should has the `lib` prefix
example: `libsum.so`, `libcalc.so`
2. The value after `LDFLAGS` should goes with name without `lib`
example:
a) `libsum.so` -> LDFLAGS=sum
a) `libcalc.so` -> LDFLAGS=calc
ChatGPT shows me a sum.c
& main.go
// sum.c
#include "sum.h"
int sum(int a, int b) {
return a + b;
}
package main
/*
#cgo LDFLAGS: -L. -lsum
#include "sum.h"
*/
import "C"
import "fmt"
func main() {
// Call the sum function from the shared library
result := C.sum(5, 7)
// Print the result
fmt.Printf("Sum: %d\n", result)
}
I had put the files into following struct:
$ tree <project_folder>
.
├── libs
│ ├── sum.c
│ └── sum.h
└── main.go
With the build script:
$ cd <project_folder>/libs
$ gcc -shared -o libsum.so sum.c
$ cd <project_folder>
$ go build -o go_sum main.go
And here comes the first error:
$ go build -o go_sum main.go
# command-line-arguments
./main.go:5:10: fatal error: sum.h: No such file or directory
5 | #include "sum.h"
| ^~~~~~~
compilation terminated.
It’s not a big deal to us to create a sum.h
header file.
// sum.h
#include <stdio.h>
int sum(int a, int b);
There should also put another compile flag: CFLAGS
for cgo in main.go
, then rebuild the Golang executable file
package main
/*
#cgo CFLAGS: -Ilibs
#cgo LDFLAGS: -Llibs -lsum
#include "sum.h"
*/
import "C"
import "fmt"
...
Once build successfully, just run the executable file with name go_sum
Unfortunately, another error pops !
$ ./go_sum
./go_sum: error while loading shared libraries: libsum.so: cannot open shared object file: No such file or directory
By searching and try-error for hours, I had found the solution which I should make the .so
file been found by linker.
Here is the command where we can track the .so
file information linked to a executable file:
$ ldd <executable file>
## Results for go_sum
$ ldd go_sum
linux-vdso.so.1 (0x00007ffde1aab000)
libsum.so => not found
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f6a85b55000)
/lib64/ld-linux-x86-64.so.2 (0x00007f6a85d86000)
As the result, the libsum.so
has not been recognized, here is nothing consider with the .so
itself, but the linker.
Solution
Updated: 2023/09/20
- By config correctly with
LDFLAGS
Thanks to the answer from Arkadiusz Rychliński
#cgo LDFLAGS: -L./lib -Wl, -rpath, $ORIGIN/libs -lsum
- By adding the
LD_LIBRARY_PATH
$ export LD_LIBRARY_PATH=<project_folder>/lib/
After the line execute, rebuild the Golang executable file, then check again the lib has been recognized with ldd
command.
$ go build -o go_sum main.go
$ ldd go_sum
linux-vdso.so.1 (0x00007ffde1aab000)
libsum.so => <project_folder>/libs/libsum.so (0x00007ff959dbb000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f6a85b55000)
/lib64/ld-linux-x86-64.so.2 (0x00007f6a85d86000)
$ ./go_sum
Sum: 12
Hope the article can help to save times.
Ref:
[1]: https://segmentfault.com/q/1010000022621510
[2]: https://serverfault.com/a/201711