如何使用调用未定义的 c 函数的 Go 构建共享库?
How do I build a shared library using Go that calls an undefined c function?
我想使用 Go 创建一个共享库,供 third-party 软件 (STAR-CCM+) 使用。该软件提供了一些实用程序 c 函数供我的代码调用,并期望我的代码 至少 定义一个特定的函数,third-party 软件将在加载后调用该函数图书馆。
我的问题是 Go 抱怨实用函数的未定义引用:
/tmp/go-build672782048/b001/_x002.o: In function `_cgo_c4b84da031f3_Cfunc_utility':
/tmp/go-build/cgo-gcc-prolog:50: undefined reference to `utility'
我如何编译一个共享库,它调用一个已声明但未由我的代码定义的 c 函数?
third-party软件提供了一个header类似这样的文件:
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
工作示例,仅 c
为了测试与第三方软件的交互,我仅使用 c:
构建了一个示例
usingc.c
#include "uclib.h"
void
user_function()
{
utility(1);
}
建造:
$ gcc -fPIC -c usingc.c -o usingc.o
$ gcc -shared -o libmine.so usingc.o
这导致 libmine.so
第三方软件成功加载并注册其 utility
函数被 1
调用。请注意,utility
仅由我的代码声明,从未定义。
有问题的例子,Go
我用上面的 header 和两个文件创建了一个简单的 go 模块:
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() {}
我尝试构建共享库并观察到错误:
$ 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
允许与未定义引用链接的三种可能的解决方案。后两个位于 golang-nuts
Google Group:
- 通过
LDFLAGS
和 -shared
忽略所有未定义的引用
// #include "uclib.h"
// #cgo LDFLAGS: -shared
import "C"
- 通过
LDFLAGS
和 -Wl,-unresolved-symbols=ignore-all
: 忽略所有未定义的引用
// #include "uclib.h"
// #cgo LDFLAGS: -Wl,-unresolved-symbols=ignore-all
import "C"
- 在头文件中标记已声明但未定义的函数as weak:
#pragma weak utility
// utility function defined by third party software, declared here
extern void utility(int);
#3 的优点是未标记为弱的引用仍被称为未定义。
我想使用 Go 创建一个共享库,供 third-party 软件 (STAR-CCM+) 使用。该软件提供了一些实用程序 c 函数供我的代码调用,并期望我的代码 至少 定义一个特定的函数,third-party 软件将在加载后调用该函数图书馆。
我的问题是 Go 抱怨实用函数的未定义引用:
/tmp/go-build672782048/b001/_x002.o: In function `_cgo_c4b84da031f3_Cfunc_utility':
/tmp/go-build/cgo-gcc-prolog:50: undefined reference to `utility'
我如何编译一个共享库,它调用一个已声明但未由我的代码定义的 c 函数?
third-party软件提供了一个header类似这样的文件:
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
工作示例,仅 c
为了测试与第三方软件的交互,我仅使用 c:
构建了一个示例usingc.c
#include "uclib.h"
void
user_function()
{
utility(1);
}
建造:
$ gcc -fPIC -c usingc.c -o usingc.o
$ gcc -shared -o libmine.so usingc.o
这导致 libmine.so
第三方软件成功加载并注册其 utility
函数被 1
调用。请注意,utility
仅由我的代码声明,从未定义。
有问题的例子,Go
我用上面的 header 和两个文件创建了一个简单的 go 模块:
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() {}
我尝试构建共享库并观察到错误:
$ 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
允许与未定义引用链接的三种可能的解决方案。后两个位于 golang-nuts
Google Group:
- 通过
LDFLAGS
和-shared
忽略所有未定义的引用
// #include "uclib.h"
// #cgo LDFLAGS: -shared
import "C"
- 通过
LDFLAGS
和-Wl,-unresolved-symbols=ignore-all
: 忽略所有未定义的引用
// #include "uclib.h"
// #cgo LDFLAGS: -Wl,-unresolved-symbols=ignore-all
import "C"
- 在头文件中标记已声明但未定义的函数as weak:
#pragma weak utility
// utility function defined by third party software, declared here
extern void utility(int);
#3 的优点是未标记为弱的引用仍被称为未定义。