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

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u014633283/article/details/52225274

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()
}

结果如下所示:
结果

猜你喜欢

转载自blog.csdn.net/u014633283/article/details/52225274
今日推荐