前往小程序,Get更优阅读体验!
立即前往
发布
社区首页 >专栏 >在Go语言中调用C代码的技巧

在Go语言中调用C代码的技巧

作者头像
蒙娜丽宁
发布2024-11-23 15:43:52
发布2024-11-23 15:43:52
7100
代码可运行
举报
文章被收录于专栏:极客起源
运行总次数:0
代码可运行

在 Go 语言中调用 C 代码的技巧

虽然 Go 语言旨在提升编程体验,减少 C 语言的复杂性,但 C 语言依然是非常强大的编程语言,并且在很多情况下依然十分有用。比如在使用数据库或设备驱动程序时,它们可能是用 C 语言编写的。这意味着在某些情况下,你可能需要在 Go 项目中调用 C 代码。

在同一个文件中调用 C 代码

最简单的调用 C 代码的方式是将 C 代码直接包含在 Go 源文件中。虽然这需要一些特殊处理,但这种方式速度很快,也不算太复杂。不过,如果你在同一个项目中多次使用这种功能,可能需要重新考虑这种方式是否合适,或者是否应该换一种编程语言。

下面展示了一个包含 C 代码和 Go 代码的文件 cGo.go,它分为三部分:

代码语言:javascript
代码运行次数:0
复制
package main  // #include <stdio.h> // void callC() { //     printf("调用 C 代码!\n"); // } import "C"  import "fmt"  func main() {     fmt.Println("这是 Go 语言中的一条语句!")     C.callC()     fmt.Println("这是另一条 Go 语言中的语句!") } 

在上面的代码中,callC() C 函数通过 C.callC() 调用。运行该代码会产生以下输出:

代码语言:javascript
代码运行次数:0
复制
$ go run cGo.go 这是 Go 语言中的一条语句! 调用 C 代码! 这是另一条 Go 语言中的语句! 
使用单独文件调用 C 代码

接下来讨论如何在 C 代码位于单独的文件时,从 Go 程序中调用它。假设我们有两个已经编写好的 C 函数,不想在 Go 中重写它们。

C 代码

首先,C 代码包含在两个文件中:callC.hcallC.c

callC.h 文件内容如下:

代码语言:javascript
代码运行次数:0
复制
#ifndef CALLC_H #define CALLC_H void cHello(); void printMessage(char* message); #endif 

callC.c 文件内容如下:

代码语言:javascript
代码运行次数:0
复制
#include <stdio.h> #include "callC.h"  void cHello() {     printf("来自 C 语言的问候!\n"); }  void printMessage(char* message) {     printf("Go 语言发送的消息是: %s\n", message); } 

这两个文件存储在 callClib 目录下。当然,你也可以使用任何其他目录名称。

Go 代码

接下来是 Go 源代码,它被命名为 callC.go,分为三部分展示:

代码语言:javascript
代码运行次数:0
复制
package main  // #cgo CFLAGS: -I${SRCDIR}/callClib // #cgo LDFLAGS: ${SRCDIR}/callC.a // #include <stdlib.h> // #include <callC.h> import "C"  import (     "fmt"     "unsafe" )  func main() {     fmt.Println("即将调用 C 函数!")     C.cHello()      fmt.Println("即将调用另一个 C 函数!")     myMessage := C.CString("这是来自 Mihalis 的消息!")     defer C.free(unsafe.Pointer(myMessage))     C.printMessage(myMessage)      fmt.Println("调用完成!") } 

在 Go 中传递字符串给 C 函数时,需要使用 C.CString() 创建一个 C 字符串,同时要使用 defer 语句来确保不再需要时释放内存。

编译和执行混合的 Go 和 C 代码

当你编写好 C 代码和 Go 代码后,接下来就是编译并执行这些文件。幸运的是,所有关键信息都已经包含在 Go 文件中,唯一的重点是编译 C 代码以创建一个静态库。你可以执行以下命令来完成这些操作:

代码语言:javascript
代码运行次数:0
复制
$ ls -l callClib/ total 16 -rw-r--r--@ 1 mtsouk  staff  162 Jan 10 09:17 callC.c -rw-r--r--@ 1 mtsouk  staff   89 Jan 10 09:17 callC.h  $ gcc -c callClib/*.c  $ ls -l callC.o -rw-r--r--  1 mtsouk  staff  952 Jan 22 22:03 callC.o  $ /usr/bin/ar rs callC.a *.o ar: creating archive callC.a  $ ls -l callC.a -rw-r--r--  1 mtsouk  staff  4024 Jan 22 22:03 callC.a 

完成这些步骤后,callC.a 文件将位于与 callC.go 文件相同的目录中。此时你可以编译 Go 代码:

代码语言:javascript
代码运行次数:0
复制
$ go build callC.go  $ ls -l callC -rwxr-xr-x  1 mtsouk  staff  2403184 Jan 22 22:10 callC 

执行生成的可执行文件:

代码语言:javascript
代码运行次数:0
复制
$ ./callC 即将调用 C 函数! 来自 C 语言的问候! 即将调用另一个 C 函数! Go 语言发送的消息是: 这是来自 Mihalis 的消息! 调用完成! 
总结

如果你只需要调用少量的 C 代码,那么在同一个 Go 文件中同时包含 C 和 Go 代码是一个简洁的选择。然而,当涉及到更复杂的项目时,创建一个静态的 C 库可能是更好的选择。

- EOF -

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2024-09-14,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 极客起源 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 在 Go 语言中调用 C 代码的技巧
    • 在同一个文件中调用 C 代码
    • 使用单独文件调用 C 代码
      • C 代码
      • Go 代码
    • 编译和执行混合的 Go 和 C 代码
    • 总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档