如何用单一Go包适配cgo与gomobile构建多平台库?
解决方案:拆分核心逻辑与CGo入口层
不用重复编写代码,只需要把核心库逻辑放在非main包,再单独写一个极简的main包作为CGo的适配入口即可,完美兼容两种构建方式。
1. 重构代码结构
- 核心库包:将所有业务逻辑、暴露给外部的函数/类型都放在一个非main包中(比如
./golibs),这部分代码是跨构建方式共享的核心。 - CGo入口包:新建一个独立的main包目录(比如
./cmd/cgoentry),仅作为CGo导出函数的薄适配层,完全复用核心库的代码。
2. 代码示例
核心库代码(./golibs/lib.go)
package golibs // 示例核心功能:加法 func Add(a, b int) int { return a + b } // 示例核心功能:生成问候语 func Greet(name string) string { return "Hello, " + name }
CGo入口代码(./cmd/cgoentry/main.go)
package main /* #include <stdlib.h> */ import "C" import "../golibs" // 根据实际路径调整,或使用模块路径 import "unsafe" //export Add func Add(a C.int, b C.int) C.int { // 调用核心库函数,仅做类型转换 return C.int(golibs.Add(int(a), int(b))) } //export Greet func Greet(name *C.char) *C.char { goStr := golibs.Greet(C.GoString(name)) // 将Go字符串转为C字符串,注意需要提供释放函数 return C.CString(goStr) } //export FreeString func FreeString(s *C.char) { // 提供给C端释放内存的函数 C.free(unsafe.Pointer(s)) } // 空main函数,满足CGo对main包的要求 func main() {}
3. 调整构建命令
CGo静态/共享库构建(针对main入口包)
# Windows共享库 go build -buildmode=c-shared -o libraries/golibs.dll ./cmd/cgoentry # Linux/macOS共享库 go build -buildmode=c-shared -o libraries/golibs.so ./cmd/cgoentry # Windows静态库 go build -buildmode=c-archive -o libraries/golibs.lib ./cmd/cgoentry # Linux/macOS静态库 go build -buildmode=c-archive -o libraries/golibs.a ./cmd/cgoentry
Gomobile移动库构建(针对核心非main包)
gomobile bind -target=android -androidapi 19 -o libraries/mobile/golibs.aar -v ./golibs
4. 优势说明
- 核心逻辑仅编写维护一次,避免重复代码。
- CGo入口层仅做类型转换和函数导出,几乎无维护成本。
- 完全满足两种构建工具的包要求,无冲突。
内容的提问来源于stack exchange,提问作者Leonardo Paci
相关产品推荐
相关产品推荐

