page contents

golang与脚本C语言互相调用

本文讲述了golang与脚本C语言互相调用!具有很好的参考价值,希望对大家有所帮助。一起跟随六星小编过来看看吧,具体如下:

attachments-2022-04-HGAy4D7R62635711cf96f.png

本文讲述了golang与脚本C语言互相调用!具有很好的参考价值,希望对大家有所帮助。一起跟随六星小编过来看看吧,具体如下:

最近由于工作原因,需要实现go语言与c语言的相互调用。由于go语言与c语言有着千丝万缕的暧昧关系,两者之间的调用可以通过语言层面实现。下文是对此的总结。

go语言调用c语言

以下为一个简短的例子:




















package main


// #include <stdio.h>

// #include <stdlib.h>

/*

void print(char *str) {

    printf("%s\n", str);

}

*/

import "C" 

import "unsafe"

 

func main() {

    s := "Hello Cgo"

    cs := C.CString(s)

    C.print(cs)

    C.free(unsafe.pointer(cs))

}

与“正常”的go代码相比,上述代码有几处“特殊”的地方:

  • 在开头的注释中出现了c语言头文件的include字样

  • 在注释中定义了c语言函数print

  • import了一个名为C的“包”

  • 在main函数中调用了上述定义的c语言函数print

首先,go源码文件中的c语言代码是需要用注释包裹的,就像上面的include头文件以及print函数定义;其次,import "C"这个语句是必须的,而且其与上面的c代码之间不能用空行分隔,必须紧密相连。这里的”C“不是包名,而是一种类似名字空间的概念,或可以理解为伪包,c语言所有语法元素均在该伪包下面;最后,访问c语法元素时都要在其前面加上伪包前缀,比如C.uint和上面代码中的C.print、C.free等。

更详细的在go中调用c语言的用法可以参考Go与C语言的互操作,本文不再一一细述。

在上面的例子中,c语言是内嵌在go代码中的,如果代码量更大更复杂的话,这显然是很不”专业“的。那么,是否可以将c语言代码从go代码中分离出去,单独定义呢?答案是肯定的,可以通过共享库的方式实现。

cgo提供了#cgo指示符可以指定go源码在编译后与哪些共享库进行链接。例子如下:
























// hello.go

package main 

// #cgo LDFLAGS: -L ./ -lhello

// #include <stdio.h>

// #include <stdlib.h>

// #include "hello.h"

import "C"

 

func main() {

    C.hello()

}

 

// hello.c

#include "hello.h"

 

void hello()

{

    printf("hello, go\n");

}

 

// hello.h

extern void hello();

其中在hello.go中,#cgo指示符后面添加LDFLAGS: -L ./ -lhello,作用是在go代码编译时,指定在当前目录查找so库并进行链接。

因此,只需要把hello.c编译成动态库,再编译go代码,即可在运行go代码的时候调用共享库中的c语言函数。指令如下:

  • gcc -fPIC -o libhello.so hello.c

  • go build -o hello

  • ./hello

c语言调用go语言

与在go中调用c源码相比,在c中使用go函数的场合较少。因为一般来说,采用高级语言作为粘合剂调用低级语言能充分发挥各自的特点,而用低级语言调用高级语言反而有可能降低低级语言的性能优势,在go中,可以使用”export + 函数名“来导出go函数为c代码所用,看一个简单的例子:












// hello.go

package main

 import "C"

import "fmt"

// export Go2C

func Go2C() {

    fmt.Println("hello, C")

}

可通过go build的编译选项,将go代码编译成共享库以供c代码调用。注意,编译so库时必须存在main及main函数(即使main函数为空)。编译指令如下:go build -v -x -buildmode=c-shared -o libhello.so hello.go

编译成功后,只需在c代码中引入新生成的头文件及编译时链接动态库即可实现go函数的调用。代码如下:










// hello.c

#include <stdio.h>

#include "libhello.h"

 

int main()

{

    Go2C();

    return 0;

}

通过gcc -o hello -L. -lhello,即可编译成可执行程序。注意,运行前必须确定共享库运行时查找路径中存在需要链接的共享库,可通过将so库路径放到/usr/lib或者修改环境变量LD_LIBRARY_PATH。

小结

go语言可以通过内嵌c代码的形式调用c语言,也可以通过调用共享库函数的方式实现;至于c语言调用go函数,则可以通过go build将go代码编译成共享库提供给c代码使用。注意,本文中的共享库均为动态共享库,至于静态共享库则未曾实验,有兴趣的可以实现一下。

更多相关技术内容咨询欢迎前往并持续关注六星社区了解详情。

想高效系统的学习Python编程语言,推荐大家关注一个微信公众号:Python编程学习圈。每天分享行业资讯、技术干货供大家阅读,关注即可免费领取整套Python入门到进阶的学习资料以及教程,感兴趣的小伙伴赶紧行动起来吧。

attachments-2022-06-jHFnIpuR629da91344374.jpeg

  • 发表于 2022-04-23 09:32
  • 阅读 ( 526 )
  • 分类:Golang

你可能感兴趣的文章

相关问题

0 条评论

请先 登录 后评论
轩辕小不懂
轩辕小不懂

2403 篇文章

作家榜 »

  1. 轩辕小不懂 2403 文章
  2. 小柒 1470 文章
  3. Pack 1135 文章
  4. Nen 576 文章
  5. 王昭君 209 文章
  6. 文双 71 文章
  7. 小威 64 文章
  8. Cara 36 文章