cgo:面向 C 接口的 Go 编程经典案例

在开始的例子中,我们的全部CGO代码都在一个Go文件中。然后,通过面向C接口编程的技术将SayHello分别拆分到不同的C文件,而main依然是Go文件。再然后,是用Go函数重新实现了C语言接口的SayHello函数。但是对于目前的例子来说只有一个函数,要拆分到三个不同的文件确实有些繁琐了。

正所谓合久必分、分久必合,我们现在尝试将例子中的几个文件重新合并到一个Go文件。下面是合并后的成果:

package main

// void SayHello(char* s);
import "C"
import "fmt"

func main() {
    C.SayHello(C.CString("hello, world!")) // C.SayHello 调用的是 Go 导出的接口函数
}

//export SayHello
func SayHello(s *C.char) {
    fmt.Println(C.GoString(s))
}

  

上面代码中 Go 的导出函数 SayHello 参数类型还是使用的 Go 中 C 的原生数据类型。 但是如果可以直接用 Go 的 string 类型则是最直接的。在 Go 1.10 中 CGO 增加了一个 GoString 预定义的 C 语言类型,用来表示 Go 语言字符串。下面是改进后的代码:

package main

// void SayHello(_GoString_ s);
import "C"
import "fmt"

func main() {
    C.SayHello("Hello, World") // C.SayHello 调用的是 Go 导出的接口函数
}

//export SayHello
func SayHello(s string) {
    fmt.Println(s)
}

 

Note: 上面代码虽然看起来都是 Go 语言代码,但是执行的时候还是从 Go 的 main 函数开始执行,到 CGO 自动生成的 C 语言版本的 SayHello 桥接函数,最后又回到了Go语言环境的SayHello函数。这个代码包含了CGO编程的精华。

 
posted @ 2025-01-20 17:43  LLSix  阅读(42)  评论(0)    收藏  举报