GO中调用C代码(CGO)中的坑 - Go语言中文社区

GO中调用C代码(CGO)中的坑


GO中调用C代码(CGO)中的坑

背景

网上有很多讲解使用CGO实现GO中调用C代码的博客。总结起来,Go中调用C一共有两种办法:

  • 第一种是将C代码直接嵌入到GO源文件中
  • 第二种是将C代码写在C文件中,再在GO文件中引入

第一种实现起来比较顺滑,按照已有的博客教程中的步骤来,基本不会出错。笔者在项目中恰好要用到第二种办法,但是按照博客(http://tonybai.com/2012/09/26/interoperability-between-go-and-c/)中的步骤来,始终得不到正确结果(这里并无批评博主Tony Bai的意思,笔者其实从中学到不少)。到网上找了很多介绍CGO使用的博客,都没能解决,几乎要崩溃的时候,从以下帖子https://groups.google.com/forum/#!topic/golang-nuts/O4RTszIyL7c 中得到启示,顺利解决问题。


问题重现

从博客http://tonybai.com/2012/09/26/interoperability-between-go-and-c/中摘取相关代码文件,其代码组织和源文件内容分别如下:
代码组织

//foo.h
int count;
void foo();
//foo.c
#include <stdio.h>
#include "foo.h"

int count = 6;
void foo() {
    printf("I am foo!n");
}
package main

// #cgo LDFLAGS: -L ./ -lfoo
// #include <stdio.h>
// #include <stdlib.h>
// #include "foo.h"
import "C"
import "fmt“

func main() {
    fmt.Println(C.count)
    C.foo()
}

按照众多博客中的方法,一般分为两步:

  • 将C文件编译成动态链接库libfoo.so
  • 使用命令go build foo.go编译生成可执行文件

但在第二步的编译过程中会出现如下“对foo未定义的引用“的错误:
这里写图片描述


问题解决

我们不需要手动地给go提供动态链接库,甚至于go根本不认识我们自己手动编译出的动态链接库。其实cgo提供了一种机制:它能够根据import”C”中引入的头文件,自动找到相应的源文件进行编译链接。这种机制的调用,需要用到go build命令。
注意:不是go build foo.go命令。go build foo.go只会单独编译foo.go文件,而不会自动编译链接相关的C源文件

因此,我们无需手动编译生成动态库。更进一步,foo.go中的代码也可以进一步精简如下:

package main 

// #include <stdio.h>
// #include <stdlib.h>
// #include "foo.h"
import "C"
import "fmt"

func main() {
    fmt.Println(C.count)
    C.foo()
}

结果如下所示:
结果

版权声明:本文来源CSDN,感谢博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/u014633283/article/details/52225274
站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。
  • 发表于 2019-08-26 16:07:43
  • 阅读 ( 2625 )
  • 分类:Go

0 条评论

请先 登录 后评论

官方社群

GO教程

猜你喜欢