Golang中使用CGO的实践与技巧
Golang中使用CGO的实践与技巧
尝试在 Windows 10 上迈出使用 cgo 的第一步,因此我阅读了这篇文章、这篇文章和这篇文章,并进行了如下操作:
C:/cgo> go mod init hasan/lib
C:/cgo> code .
main.go
package main
import "C"
import "fmt"
//export HelloWorld
func HelloWorld() {
fmt.Printf("hello world")
}
func main() {}
编译过程如下:
C:/cgo> go build -buildmode=c-shared
C:/cgo> dir
Directory of C:\cgo
06/06/2020 02:23 PM <DIR> .
06/06/2020 02:23 PM <DIR> ..
06/06/2020 01:41 PM 26 go.mod
06/06/2020 02:23 PM 3,503,249 lib
06/06/2020 02:23 PM 1,580 lib.h
06/06/2020 01:42 PM 170 main.go
4 File(s) 3,505,025 bytes
然后在另一个目录 cgotest 中创建了另一个模块,创建了一个名为 hello.go 的 Go 文件,并将 lib 和 lib.h 复制到该目录:
C:/cgotest> dir
Directory of C:\cgotest
06/06/2020 02:18 PM <DIR> .
06/06/2020 02:18 PM <DIR> ..
06/06/2020 02:17 PM 24 go.mod
06/06/2020 02:18 PM 134 hello.go
06/06/2020 02:18 PM 3,503,249 lib
06/06/2020 02:18 PM 1,580 lib.h
4 File(s) 3,504,987 bytes
hello.go 的内容是:
package main
// #cgo CFLAGS: -g -Wall
// #include <stdlib.h>
// #include "lib.h"
import "C"
func main() {
HelloWorld()
}
尝试使用 go run 运行,但出现如下错误:
D:\cgotest>go run .
# lintest
.\hello.go:9:2: undefined: HelloWorld
更多关于Golang中使用CGO的实践与技巧的实战教程也可以访问 https://www.itying.com/category-94-b0.html
据我所知,从C语言导入的内容位于 C 包中。所以应该是 C.HelloWorld()。
更多关于Golang中使用CGO的实践与技巧的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
NobbZ:
C.HelloWorld()
我遇到了以下错误,请注意我是在 Windows 10 笔记本电脑上工作的。
D:\cgotest>go run .
# lintest
C:\Users\HASAN~1.YOU\AppData\Local\Temp\go-build829713742\b001\_x002.o: In function `_cgo_cd3f93e214f7_Cfunc_HelloWorld':
/tmp/go-build/cgo-gcc-prolog:49: undefined reference to `HelloWorld'
collect2.exe: error: ld returned 1 exit status
# lintest
cgo-gcc-prolog: In function '_cgo_cd3f93e214f7_Cfunc_HelloWorld':
cgo-gcc-prolog:47:49: warning: unused variable '_cgo_a' [-Wunused-variable]
在Go中使用CGO调用C共享库时,需要正确声明C函数。你的hello.go文件缺少对HelloWorld函数的C声明。以下是修正后的代码:
package main
// #cgo CFLAGS: -g -Wall
// #cgo LDFLAGS: -L. -llib
// #include <stdlib.h>
// #include "lib.h"
import "C"
func main() {
C.HelloWorld()
}
关键修改:
- 添加了
#cgo LDFLAGS: -L. -llib来链接当前目录的lib文件 - 调用时使用
C.HelloWorld()而不是HelloWorld()
另外,确保你的lib.h文件包含正确的函数声明。根据你的Go代码生成的C头文件应该包含:
/* Created by "go tool cgo" - DO NOT EDIT. */
...
#ifdef __cplusplus
extern "C" {
#endif
extern void HelloWorld();
#ifdef __cplusplus
}
#endif
如果问题仍然存在,可以尝试以下完整示例:
lib/main.go:
package main
import "C"
import "fmt"
//export HelloWorld
func HelloWorld() {
fmt.Println("hello world from Go")
}
func main() {}
编译共享库:
go build -buildmode=c-shared -o libexample.dll
client/main.go:
package main
// #cgo LDFLAGS: -L. -lexample
// #include "libexample.h"
import "C"
func main() {
C.HelloWorld()
}
运行客户端:
set PATH=%PATH%;.
go run main.go
在Windows上还需要注意:
- DLL文件需要在PATH环境变量中或当前目录
- 使用
-lexample时不需要写.dll扩展名 - 确保生成的
libexample.h头文件与客户端代码在同一目录
如果仍有链接错误,可以尝试显式指定DLL路径:
// #cgo LDFLAGS: -L${SRCDIR} -lexample
// #include "${SRCDIR}/libexample.h"
import "C"

