I want to create a shared library, using Go, to be used by a third-party software (STAR-CCM+). That software provides some utility c functions for my code to call, and expects my code to, at a minimum, define a specific function, which the third-party software will call after loading the library.
My problem is Go complains about undefined references for the utility functions:
/tmp/go-build672782048/b001/_x002.o: In function `_cgo_c4b84da031f3_Cfunc_utility':
/tmp/go-build/cgo-gcc-prolog:50: undefined reference to `utility'
How can I compile a shared library that calls a c function that is declared but not defined by my code?
The third-party software provides a header file similar to this:
uclib.h
#ifndef UCLIB_H
#define UCLIB_H
// utility function defined by third party software, declared here
extern void utility(int);
// function expected to exist in .so and defined by user
// this function is expected to call `utility` one or more times
void user_function();
#endif
To test the interaction with the third party software, I build an example using only c:
usingc.c
#include "uclib.h"
void
user_function()
{
utility(1);
}
Build:
$ gcc -fPIC -c usingc.c -o usingc.o
$ gcc -shared -o libmine.so usingc.o
This results in a libmine.so
that the third party software successfully loads and registers its utility
function being called with 1
. Note that utility
was only declared, never defined, by my code.
I create a simple go module with the header above and two files:
go.mod
module example.com/cgo_mwe
go 1.15
usinggo.go
package main
// #include "uclib.h"
import "C"
//export user_function
func user_function() {
C.utility(C.int(2))
}
func main() {}
I attempt to build the shared library and observe the error:
$ go build -o libmineg.so -buildmode=c-shared
# example.com/cgo_mwe
/tmp/go-build672782048/b001/_x002.o: In function `_cgo_c4b84da031f3_Cfunc_utility':
/tmp/go-build/cgo-gcc-prolog:50: undefined reference to `utility'
collect2: error: ld returned 1 exit status
The are three possible solutions to allow the linking with the undefined reference. The second two are found in the golang-nuts
Google Group:
LDFLAGS
with -shared
// #include "uclib.h"
// #cgo LDFLAGS: -shared
import "C"
LDFLAGS
with -Wl,-unresolved-symbols=ignore-all
:// #include "uclib.h"
// #cgo LDFLAGS: -Wl,-unresolved-symbols=ignore-all
import "C"
#pragma weak utility
// utility function defined by third party software, declared here
extern void utility(int);
The advantage of #3 is that references not marked weak are still called out as undefined.