美文网首页
cgo笔记二:C代码模块化

cgo笔记二:C代码模块化

作者: 梦回上玄 | 来源:发表于2021-03-25 11:42 被阅读0次

前言:这也是我记录cgo笔记的初衷,我偶尔需要把同事的c代码拿来用(白嫖),又不想展示自己可怜的C代码水平(毕竟没时间研究代码),so...

C代码模块化

这还是使用原作者(go语言高级编程)的一个例子,抽象一个名为hello的模块,模块的全部接口函数都在hello.h头文件定义:

//hello.h
void SayHello(const char* s);
// hello.c
#include "hello.h"
#include <stdio.h>

void SayHello(const char* s) {
    puts(s);
}
package main

/*
#include <hello.h>
*/
import "C"

func main() {
    C.SayHello(C.CString("Hello, Worldn"))
}

使用 go run . 进行运行发现程序可以正常运行。go mod可能会报错,初始化go mod即可。

静态库

如果有源码的情况下最好,但是也有时候,同事不给源码,只给库文件,这个时候就需要我们做相关调用了
我们先用纯C语言构造一个简单的静态库。我们要构造的静态库名叫number,库中只有一个number_add_mod函数,用于表示数论中的模加法运算。number库的文件都在number目录下。
number/number.h头文件只有一个纯C语言风格的函数声明:

//源码:《go语言高级编程》
//number/number.h
int number_add_mod(int a, int b, int mod);

number/number.c对应函数的实现:

//源码:《go语言高级编程》
#include "number.h"
int number_add_mod(int a, int b, int mod) {
    return (a+b)%mod;
}

因为CGO使用的是GCC命令来编译和链接C和Go桥接的代码。因此静态库也必须是GCC兼容的格式。
通过以下命令可以生成一个叫libnumber.a的静态库:

$ cd ./number
$ gcc -c -o number.o number.c
$ ar rcs libnumber.a number.o

创建main.go文件如下:

package main

//#cgo CFLAGS: -I./number
//#cgo LDFLAGS: -L${SRCDIR}/number -lnumber
//
//#include "number.h"
import "C"
import "fmt"

func main() {
    fmt.Println(C.number_add_mod(10, 5, 12))
}

其中有两个#cgo命令,分别是编译和链接参数。CFLAGS通过-I./number将number库对应头文件所在的目录加入头文件检索路径。LDFLAGS通过-L${SRCDIR}/number将编译后number静态库所在目录加为链接库检索路径,-lnumber表示链接libnumber.a静态库。需要注意的是,在链接部分的检索路径不能使用相对路径(C/C++代码的链接程序所限制),我们必须通过cgo特有的${SRCDIR}变量将源文件对应的当前目录路径展开为绝对路径(因此在windows平台中绝对路径不能有空白符号)
因为我们有number库的全部代码,所以我们可以用go generate工具来生成静态库,或者是通过Makefile来构建静态库。因此发布CGO源码包时,我们并不需要提前构建C静态库。

动态库

上面的源码,编译成动态库

$ cd number
$ gcc -shared -o libnumber.so number.c

因为动态库和静态库的基础名称都是libnumber,只是后缀名不同而已。因此Go语言部分的代码和静态库版本完全一样:

package main

//#cgo CFLAGS: -I./number
//#cgo LDFLAGS: -L${SRCDIR}/number -lnumber
//
//#include "number.h"
import "C"
import "fmt"

func main() {
    fmt.Println(C.number_add_mod(10, 5, 12))
}

编译时GCC会自动找到libnumber.a或libnumber.so进行链接。当然根据我的实际情况,我基本上不需要动态库链接。

相关文章

  • cgo笔记二:C代码模块化

    前言:这也是我记录cgo笔记的初衷,我偶尔需要把同事的c代码拿来用(白嫖),又不想展示自己可怜的C代码水平(毕竟没...

  • CGO编程

    1)什么是CGO编程?2)CGO语法3)相关资料 一、什么是CGO编程?简单说就是GO语言代码中可以编写C代码和调...

  • (1)Cgo结构

    总结: 1、import "C" 是启用Cgo,以及cgo配置,头文件,C函数2、需要调用的C语言的内容使用/**...

  • Go与c++混合编程

    利用cgo实现go调用c/c++的接口

  • cgo

    cgo cgo是用来在Go语言中调用C语言的工具 Go语言调用C语言 简单C语言函数 在Go语言中需要通过impo...

  • golang调用c语言代码-cgo方式

    1.cgo简单调用 官方文档:The Go file will have access to anything a...

  • cgo

    转载一篇CGO的文章 Go 与 C 的桥梁:cgo 入门,剖析与实践[https://zhuanlan.zhihu...

  • Go: build constraints exclude al

    适用场景: 项目采用CGO编程 解决方案: 设置环境变量中的CGO_ENABLED 支持C...

  • C++基础高频问题(一)

    1.C++三个特性 封装:使代码模块化。继承:在不改变原有模块化代码的基础上对功能进行扩展,以达到代码复用的目的。...

  • [golang]如何在windows上使用cgo

    golang的cgo是调用gcc编译c代码的,gcc工具链在linux上很方便,但windows上是没有的。而wi...

网友评论

      本文标题:cgo笔记二:C代码模块化

      本文链接:https://www.haomeiwen.com/subject/qislhltx.html