跳转到主内容
趣航编程网 - 趣学编程,启航技术之路!

golang如何编译动态库_golang动态库编译方法

Go 1.15+ 不支持生成可被非C程序直接dlopen的通用动态库,仅支持buildmode=c-shared生成带C ABI的封装库,依赖Go运行时且必须由C程序调用。 Go 1.15+ 不支持直接编译传统 .so 动态库 Go 官方从 Go 1.15 开始移除了
buildmode=c-shared
对非 C 语言主程序的动态链接支持,且 Go 本身不生成 ELF/Dylib 风格的、可被其他语言(如 Python、C)直接
dlopen
加载的通用动态库。所谓“Go 动态库”,实际仅指
buildmode=c-shared
生成的带 C ABI 的封装层 —— 它依赖 Go 运行时,必须由 C 程序调用,不能脱离 Go 生态独立加载。 用 buildmode=c-shared 生成 C 兼容接口 这是唯一受官方支持的“动态库”路径,产出
.so
(Linux)或
.dylib
(macOS),但本质是 C 接口桥接 + 内嵌 Go 运行时。需严格满足: 主包必须是
package main
,且只含
export
函数(用
//export FuncName
注释标记) 必须导入
"C"
包(即使没显式使用) 导出函数参数/返回值只能是 C 兼容类型:
C.int
*C.char
C.size_t
等,不能是 Go 的
string
slice
struct
需手动管理内存:Go 分配的内存(如
C.CString
)必须在 C 侧调用
C.free
释放 示例:
// hello.go package main import "C" import "unsafe" //export Add func Add(a, b int) int { return a + b } //export Hello func Hello(s *C.char) *C.char { goStr := C.GoString(s) ret := C.CString("Hello, " + goStr) return ret } func main() {} // required, but not executed
编译命令: 立即学习 “ go语言免费学习笔记(深入) ”; go语言参考手册 中文CHM版 Go 是一个开源的编程语言,它能让构造简单、可靠且高效的软件变得容易。本文给大家带来Go参考手册,需要的可以来下载! Go是从2007年末由Robert Griesemer, Rob Pike, Ken Thompson主持开发,后来还加入了Ian Lance Taylor, Russ Cox等人,并最终于2009年11月开源,在2012年早些时候发布了Go 1稳定版本。现在Go的开发已经是完全开放的,并且拥有一个活跃的社区。 Go 语言特色 简洁、快速、安全 并行、有趣、开源 内存管理、v数组安全、编译 下载
go build -buildmode=c-shared -o libhello.so hello.go
调用时必须链接 lib go 和 libc,且不能静态链接 Go 运行时 生成的
.so
不是纯代码,它依赖 Go 运行时符号(如
runtime.mallocgc
)。C 程序调用时: 必须用
gcc
(不是
clang
默认配置)链接,且顺序为:
your_app.c libhello.so -lgo -lpthread
不能加
-static
,否则链接失败 —— Go 运行时不支持全静态链接到外部程序 运行时需确保
LD_LIBRARY_PATH
包含
libhello.so
路径,否则
dlopen
找不到依赖 首次调用任意导出函数会触发 Go 运行时初始化,后续调用才真正执行逻辑 替代方案:CGO + 纯 C 库更可控 如果目标是让 Python/Java/Rust 调用 Go 逻辑,
c-shared
很容易因运行时冲突、GC 干预、线程模型不匹配出问题。更稳的做法是: 用 Go 实现核心逻辑,通过
c-shared
暴露极简 C 接口(只做数据转换,不启动 goroutine、不调用
net/http
等) 把 Go 编译成静态链接的
.a
库,再用纯 C 封装一层,对外提供标准 POSIX 动态库接口 或改用
gopy
go get github.com/go-python/gopy
)生成 Python 绑定,绕过 C ABI 层 真正麻烦的从来不是编译命令,而是 Go 运行时与宿主环境的生命周期耦合 —— 比如 Python 的 GIL、Java 的 JNI Attach/Detach、C 程序的 fork 处理,都可能让 Go 的调度器卡死或泄露 goroutine。

相关文章