热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

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

GO中调用C代码(CGO)中的坑GO中调用C代码CGO中的坑背景问题重现问题解决背景网上有很多讲解使用CGO实现GO中调用C代码的博客。总结起来,Go中调用C一共有两种办法:第一种是将

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
#include "foo.h"

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

// #cgo LDFLAGS: -L ./ -lfoo
// #include
// #include
// #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
// #include
// #include "foo.h"
import "C"
import "fmt"

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

结果如下所示:
结果


推荐阅读
  • 本文介绍了Hyperledger Fabric外部链码构建与运行的相关知识,包括在Hyperledger Fabric 2.0版本之前链码构建和运行的困难性,外部构建模式的实现原理以及外部构建和运行API的使用方法。通过本文的介绍,读者可以了解到如何利用外部构建和运行的方式来实现链码的构建和运行,并且不再受限于特定的语言和部署环境。 ... [详细]
  • baresip android编译、运行教程1语音通话
    本文介绍了如何在安卓平台上编译和运行baresip android,包括下载相关的sdk和ndk,修改ndk路径和输出目录,以及创建一个c++的安卓工程并将目录考到cpp下。详细步骤可参考给出的链接和文档。 ... [详细]
  • 微软头条实习生分享深度学习自学指南
    本文介绍了一位微软头条实习生自学深度学习的经验分享,包括学习资源推荐、重要基础知识的学习要点等。作者强调了学好Python和数学基础的重要性,并提供了一些建议。 ... [详细]
  • vue使用
    关键词: ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • 本文介绍了数据库的存储结构及其重要性,强调了关系数据库范例中将逻辑存储与物理存储分开的必要性。通过逻辑结构和物理结构的分离,可以实现对物理存储的重新组织和数据库的迁移,而应用程序不会察觉到任何更改。文章还展示了Oracle数据库的逻辑结构和物理结构,并介绍了表空间的概念和作用。 ... [详细]
  • 原文地址:https:www.cnblogs.combaoyipSpringBoot_YML.html1.在springboot中,有两种配置文件,一种 ... [详细]
  • Android Studio Bumblebee | 2021.1.1(大黄蜂版本使用介绍)
    本文介绍了Android Studio Bumblebee | 2021.1.1(大黄蜂版本)的使用方法和相关知识,包括Gradle的介绍、设备管理器的配置、无线调试、新版本问题等内容。同时还提供了更新版本的下载地址和启动页面截图。 ... [详细]
  • 使用Ubuntu中的Python获取浏览器历史记录原文: ... [详细]
  • 本文介绍了Perl的测试框架Test::Base,它是一个数据驱动的测试框架,可以自动进行单元测试,省去手工编写测试程序的麻烦。与Test::More完全兼容,使用方法简单。以plural函数为例,展示了Test::Base的使用方法。 ... [详细]
  • 本文介绍了计算机网络的定义和通信流程,包括客户端编译文件、二进制转换、三层路由设备等。同时,还介绍了计算机网络中常用的关键词,如MAC地址和IP地址。 ... [详细]
  • 关键词:Golang, Cookie, 跟踪位置, net/http/cookiejar, package main, golang.org/x/net/publicsuffix, io/ioutil, log, net/http, net/http/cookiejar ... [详细]
  • 本文介绍了Android 7的学习笔记总结,包括最新的移动架构视频、大厂安卓面试真题和项目实战源码讲义。同时还分享了开源的完整内容,并提醒读者在使用FileProvider适配时要注意不同模块的AndroidManfiest.xml中配置的xml文件名必须不同,否则会出现问题。 ... [详细]
  • Android源码深入理解JNI技术的概述和应用
    本文介绍了Android源码中的JNI技术,包括概述和应用。JNI是Java Native Interface的缩写,是一种技术,可以实现Java程序调用Native语言写的函数,以及Native程序调用Java层的函数。在Android平台上,JNI充当了连接Java世界和Native世界的桥梁。本文通过分析Android源码中的相关文件和位置,深入探讨了JNI技术在Android开发中的重要性和应用场景。 ... [详细]
  • 本文介绍了在多平台下进行条件编译的必要性,以及具体的实现方法。通过示例代码展示了如何使用条件编译来实现不同平台的功能。最后总结了只要接口相同,不同平台下的编译运行结果也会相同。 ... [详细]
author-avatar
15-Sports
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有