概述
简介:
go语言通过自带的一个叫cgo的工具来支持c语言函数调用,同事我们可以用Go语言导出c动态库给其他语言使用。
2.1 快速入门
1、没有释放使用C.CString创建的C语言字符串会导致内存泄漏。
2、需要通过extern "C"语句指示该函数的链接符号遵循C语言的规则。
3、cgo不仅用于Go语言中调用C语言函数,还可以用于导出Go语言函数给C函数调用。
4、通过CGO//export SayHello指令将Go语言实现的函数SayHello()导出为C语言函数。为了适配
CGO导出的C语言函数,我们禁止了在函数的声明语句中的const修饰符。需要注意的是,这里其实有
两个版本的SayHello函数的版本:一个go语言环境的,一个是C语言环境的。
cgo生成的C语言版本的SayHello函数最终会通过桥接代码调用Go语言版本的SayHello函数。
5、在Go1.10中CGO新增加了一个_GoString_预定义的C语言类型,用来表示Go语言字符串。
2.2 CGO基础
1、开头的注释中写了要调用的C函数和相关的头文件,头文件被include之后里面所有的C语言元素都会被
加入“C”这个虚拟的包中。
2、通过虚拟的C包导入的C语言符号并不需要以大写字母开头,不受Go语言的导出规则约束。
3、不同的Go语言包引入的虚拟C包之间的类型是不能通用的。这导致从他们延伸出来的go类型也是不同的类型
一个包如果在公开的接口中直接使用了*C.char等类似的虚拟C包的类型,其他go包无法直接使用这些类型的。
除非这个go包同时也提供了*C.char类型的构造函数。
4、#cgo语句在import "C"语句前的注释中可以通过#cgo语句设置编译阶段和链接阶段的相关
参数。在库文件的检索目录中可以通过$(SRCDIR)变量表示当前包目录的绝对路径。
5、#cgo语句还支持条件选择,当满足某个操作系统和某个CPU架构类型时,后面的编译选项生效。
6、不同的系统下CGO对应着不同的C代码,可用#CGO语句定义不同的宏。
7、build标志条件编译,
2.3类型转换
1、go访问c的符号时,一般是通过虚拟的“C”包访问的,有些c语言的类型是由多个关键字组成的,
因此CGO为C语言的基础数字类型都提供了相应转换规则。注意点:c语言中int、short等类型没有
明确定义内存大小,但是CGO中他们内存的大小确定的。在CGO中,c的int和long都是对应4个
字节的。
2、在c语言中访问go语言的int类型,可以通过GoInt类型访问,GoInt在CGO生成_cgo_export.h头
文件中定义。
3、go字符串和切片,在_cgo_export.h头文件中还会为Go语言的字符串、切片、字典、接口和通道
等特有的数据类型生成对应的C语言类型。只有字符串和切片在CGO中有一定的使用价值。因为CGO
为其提供了辅助函数。使用GoString类型会对_cgo_export.h产生依赖,go1.10对go字符串增加了
_GoString_预定义类型,减少对_cgo_export.h的依赖。同事go1.10还增加对_GoString_操作的辅助
函数。
4、结构体、联合和枚举类型,c语言结构体中的位字段对应的成员无法在go语言中访问,
如果需要操作位字段成员,需要通过在c语言中定义辅助函数来完成。也无法访问零长的数组
成员。在c语言中,无法直接访问go语言定义的结构体类型。
5、数组、字符串和切片,
总结:
1、go语言通过自带的cgo工具来支持对c语言函数的调用,同时也可以使用go语言导出C动态库
给其他语言使用。
2、代码通过import "C"来开启cgo特性,go build命令在编译和链接阶段启动gcc编译器。
3、包含<stdio.h>头文件通过C虚拟包的C.CString(...)来构造字符串,C.CString(...)调用
malloc克隆字符串,使用结束后需要调用C.Free(...)来释放内存。
4、go调用自定义的C接口函数需要删除static,否则外部无法使用。
5、go调用的c函数可以以静态库和动态库的形式被go使用。
6、c函数实现文件并不是一定要以.c文件,可以以.cpp文件存在,但是一定要加入extern "C" 告诉
C++编译器要按照C的函数编译方式编译,指示函数的链接符号遵循C语言的规则,符号C语言API
接口编程规范。CGO不支持C++语法的根本原因是C++至今没有一个二进制接口规范。
7、可以用go实现C语言的函数,可以通过CGO的//export functionname指令将Go语言实现的函数
导出为C语言函数。此时会产生两个版本的函数,一个是go语言环境的,一个是c语言环境的。
cgo生成的c语言版本的函数会通过桥接代码调用go语言版本的函数。
8、在go1.10中cgo新增了一个_GoString_预定义的C语言类型,用来表示go语言字符串。
9、cgo在本地构建时cgo默认是开启的环境CGO_ENABLED:1,交叉构建时cgo默认时禁止的
CGO_ENABLED:0。在环境变量为1,然后通过import "C"语句来启用CGO特性。
10、import “C”语句紧邻这行语句前面的注释是一种特殊语法,里面包含正常C的代码。
在确保CGO启用的情况下,还可以在当前目录下包含C/c++对应的源文件。import "C"需要单独一行。
11、数值类型go访问c语言中的符号,一般是通过虚拟包“C”包访问的,如C.int对应c语言的int类型。
有些c语言的类型是多个关键字组成的,但是通过虚拟包“C”访问c语言类型不能有空格。cgo为c语言的
基础类型做了规则转换。如:C.uint对应C语言的unsigned int。
12、在c中int、short等类型没有明确定义大小,但是在cgo中内存大小是确定的,都是4个字节。
13、c语言中访问go语言的类型,每个基本的go数值类型都定义了对应的C语言类型,一般以单词Go
为前缀。除了GoInt和GoUint之外,我们并不直接推荐访问GoInt32、GoInt64等类型。更好的是
通过C语言的C99标准引入<stdint.h>头文件。
14、go字符串和切片,
最后
以上就是发嗲毛衣为你收集整理的cgo编程的全部内容,希望文章能够帮你解决cgo编程所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复