当前位置:网站首页>CGO Preliminary Cognition and Basic Data Type Conversion
CGO Preliminary Cognition and Basic Data Type Conversion
2022-08-10 21:14:00 【Abing cloud native】
CGO 是什么?
CGO 是 GO 语言里面的一个特性,CGO 属于 GOLANG 的高级用法,主要是通过使用 GOLANG 调用 CLANG Implemented library
使用
我们可以使用
import "C"
来使用 CGO 这个特性
一个最简单的 CGO 使用
package main
//#include <stdio.h>
import "C"
func main(){
C.puts(C.CString("Hello, Cgo\n"))
}
import "C"
The above can write the library that needs to be imported C 库,need to be annotated,CGO The comments here will be treated as such C 的代码,被称为序文(preamble)
Functional explanation of the above code
使用 CGO 包的
C.CString
函数将 Go The language string is converted to C 语言字符串最后调用 CGO 包的
C.puts
The function prints the converted to the standard output window C 字符串
使用 go build -x main.go
编译一下
加上 -x
Instructions executed during compilation can be printed out
# go build -x main.go
WORK=/tmp/go-build594331603
mkdir -p $WORK/b001/
cat >$WORK/b001/importcfg.link << 'EOF' # internal packagefile command-line-arguments=/root/.cache/go-build/fb/fbb37eeb6735cb453f6d92e2e3f46f14d9dceb5baa1cdd10aae11d1d47d60e55-d packagefile runtime/cgo=/usr/local/go/pkg/linux_amd64/runtime/cgo.a packagefile syscall=/usr/local/go/pkg/linux_amd64/syscall.a packagefile runtime=/usr/local/go/pkg/linux_amd64/runtime.a packagefile errors=/usr/local/go/pkg/linux_amd64/errors.a packagefile internal/bytealg=/usr/local/go/pkg/linux_amd64/internal/bytealg.a packagefile internal/oserror=/usr/local/go/pkg/linux_amd64/internal/oserror.a packagefile internal/race=/usr/local/go/pkg/linux_amd64/internal/race.a packagefile internal/unsafeheader=/usr/local/go/pkg/linux_amd64/internal/unsafeheader.a packagefile sync=/usr/local/go/pkg/linux_amd64/sync.a packagefile internal/cpu=/usr/local/go/pkg/linux_amd64/internal/cpu.a packagefile runtime/internal/atomic=/usr/local/go/pkg/linux_amd64/runtime/internal/atomic.a packagefile runtime/internal/math=/usr/local/go/pkg/linux_amd64/runtime/internal/math.a packagefile runtime/internal/sys=/usr/local/go/pkg/linux_amd64/runtime/internal/sys.a packagefile internal/reflectlite=/usr/local/go/pkg/linux_amd64/internal/reflectlite.a packagefile sync/atomic=/usr/local/go/pkg/linux_amd64/sync/atomic.a EOF
mkdir -p $WORK/b001/exe/
cd .
/usr/local/go/pkg/tool/linux_amd64/link -o $WORK/b001/exe/a.out -importcfg $WORK/b001/importcfg.link -buildmode=exe -buildid=Vv0to6CWqbWf5_KTN66F/K36AEO-x4qJ_LJbz5wgG/HVbBbLSaW0sTSwlN8TzN/Vv0to6CWqbWf5_KTN66F -extld=gcc /root/.cache/go-build/fb/fbb37eeb6735cb453f6d92e2e3f46f14d9dceb5baa1cdd10aae11d1d47d60e55-d
/usr/local/go/pkg/tool/linux_amd64/buildid -w $WORK/b001/exe/a.out # internal
mv $WORK/b001/exe/a.out main
rm -r $WORK/b001/
尝试自己写一个 C 函数,让 GO 来调用他
Gocall this in the locale SayHello
函数
package main
/*
#include <stdio.h>
static void SayHello(const char* s) {
puts(s);
}
*/
import "C"
func main(){
C.SayHello(C.CString("hello xiaomotong study cgo\n"))
}
尝试自己写一个 C 文件,然后 GO Import and call in
xmtC.h
void SayHi(const char * str);
xmtC.c
(Must be in the same directory .c 文件,cgo 使用 go build 编译的时候,It will be found in the same directory by default.c
文件进行编译,If we need to C The file is made into a static library 或者 动态库的方式,Then don't C The source code files are placed in the same directory,避免重名)
#include <stdio.h>
#include "xmtC.h"
void SayHi(const char * str){
puts(str);
}
main.go
package main
//void SayHi(const char * str);
import "C"
func main(){
C.SayHi(C.CString("hello xiaomotong study cgo\n"))
}
直接运行go build
进行编译,Just run the executable program
# go build
# ls
cgo main.go xmtC.c
# ./cgo
hello xiaomotong study cgo
通过面向CProgramming techniques for language interfaces,We don't just free up implementors of functions,It also simplifies the user of the function.现在我们可以将 SayHi Used as a standard library function(和putsFunctions are used in a similar way)
咱们也可以在 go The file is written like this
package main
//#include <xmtC.h>
import "C"
func main(){
C.SayHi(C.CString("hello xiaomotong study cgo\n"))
}
合并 C 和 GO 的代码
在Go1.10
中CGO新增加了一个_GoString_
预定义的C语言类型,用来表示Go语言字符串
// +build go1.10
package main
//void SayHi(_GoString_ s);
import "C"
import (
"fmt"
)
func main() {
C.SayHi("hello xiaomotong study cgo\n")
}
//export SayHi
func SayHi(s string) {
fmt.Print(s)
}
The specific execution logic sequence of the above code is as follows:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9ynH1W4H-1659626343404)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/f70064ec5d9d4b1b9ec0ce5579f8d35f~tplv-k3u1fbpfcp-zoom-1.image)]
CGO 环境
使用 CGO Some environmental support is required
- linux 下 需要有
gcc/g++
的编译环境 - windows Need to have MinGW 工具
- 需要把 GO 的环境变量
CGO_ENABLED
置位 1
上述的例子中,We have a few points to note:
import "C"
Statements cannot be combined with other import 语句放在一起,It needs to be placed on a separate line上述我们在GOthe value passed inside,例如
C.CString("hello xiaomotong study cgo\n")
是调用了 C virtual package,将字符串转换成 C The string passed inGo是强类型语言
所以 cgo The parameter type passed in must exactly match the declared type,And it must be used before delivery ”C” The transformation function in is converted into the corresponding C类型,不能直接传入Govariable of type
通过虚拟的 C 包导入的Clanguage symbolsIt does not need to start with a capital letter,它们不受GoThe language's export rule constraints
#cgo 用法
我们可以使用 #cgo
The statement sets the relevant parameters of the compilation phase and the linking phase
- Compile phase parameters
Mainly used to define related macros and specify the header file retrieval path
- Parameters for the linking phase
Mainly specify the library file retrieval path and the library file to be linked
例如我们可以这样
// #cgo CFLAGS: -DPNG_DEBUG=1 -I./include
// #cgo LDFLAGS: -L/usr/local/lib -lpng
// #include <png.h>
import "C"
CFLAGS
- -DPNG_DEBUG
定义宏 PNG_DEBUG ,设置为 1
- -I
The search directory for defining header files is ./include
LDFLAGS
- -L
Specifies the link-time library file retrieval directory ,可以通过写 ${SRCDIR}
to represent the absolute path of the current package
- -l
指定链接时需要的库,此处是 png 库
条件编译 build tag
就是在我们 go build
的时候,Add some conditional parameters,Of course, this conditional parameter is required in the corresponding file,
For example above we use Go1.10
的时候,just added in the file // +build go1.10
我们可以这样用:
go build -tags="debug"
go build -tags="debug test"
go build -tags="linux,386"
go build 的时候加上 -tags
参数,If there are more than one, we can write them together,用空格
间隔,表示 或
,用逗号
interval representation与
GO 和 C 数据类型相互转换
cgo The official provides the following data type conversions:
C语言类型 | CGO类型 | Go语言类型 |
---|---|---|
char | C.char | byte |
singed char | C.schar | int8 |
unsigned char | C.uchar | uint8 |
short | C.short | int16 |
unsigned short | C.ushort | uint16 |
int | C.int | int32 |
unsigned int | C.uint | uint32 |
long | C.long | int32 |
unsigned long | C.ulong | uint32 |
long long int | C.longlong | int64 |
unsigned long long int | C.ulonglong | uint64 |
float | C.float | float32 |
double | C.double | float64 |
size_t | C.size_t | uint |
需要注意 3 个点:
CGO 中,C 语言的
int
和long
Types are corresponding4个字节的内存大小,size_t
类型可以当作Go语言uint
Unsigned integer types are treatedCGO 中,C 语言的
int
固定为4字节的大小 , GO 语言的int
和uint
却在32位和64Correspondingly under the bit system 4 个字节和 8 个字节大小For example, there are spaces between data types,
unsigned int
不能直接通过C.unsigned int
访问,可以使用typedef
The keyword provides a type of rule named,This is more beneficialCGO中访问
String and slice types
CGO生成的 _cgo_export.h
头文件中有 GO 里面字符串,切片,通道,字典,The corresponding representation of data types such as interfaces,But we generally use strings and slices that are valuable
因为 CGO No helper functions are provided for other data types
typedef struct {
const char *p; GoInt n; } GoString;
We can write this when we export the function:
使用 _GoString_
预定义类型,Writing this way can reduce the cgo Probably right in the code _cgo_export.h
Risk of circular dependencies created by header files
_GoString_
是 Go1.10 针对 Go special characters
extern void helloString(_GoString_ p0);
We can use officially provided functions计算字符串的长度 和 获取字符串的地址:
size_t _GoStringLen(_GoString_ s);
const char *_GoStringPtr(_GoString_ s);
struct ,union,enum
GO 语言中访问 C 语言的 struct ,union,enum,You can view the corresponding relationship in the table below
C语言 | GO 语言 |
---|---|
struct xx | C.struct_xx |
union xx | C.union_xx |
enum xx | C.enum_xx |
**对于结构体 struct **
The memory layout of the structure follows C General alignment rules for the language
在32位Go语言环境 C The language structure also follows32Bit alignment rules,在64位GoLocale as per64Bit alignment rules
For structures that specify special alignment rules,无法在 CGO 中访问
GO can be accessed like this C 的结构体
package main
/* struct struct_TEST { int i; float f; }; */
import "C"
import "fmt"
func main() {
var a C.struct_TEST
a.i = 1
a.f = 2
fmt.Println(a.i)
fmt.Println(a.f)
}
需要注意如下 2 个大点:
- The names and struct members GO The names of the keywords are handled the same way
For example, the above structure member names are like this
struct struct_TEST {
int type;
float f;
};
那么我们访问 type 的时候,可以这样访问a._type
即可
If the structure is like this?
struct struct_TEST {
int type;
float _type;
};
It was still the same when we visited, a._type
,But the actual visit is float _type;
,通过 GO There is no way to access int type;
GO also cannot be accessed C 中的 零长数组 和 位字段,例如
struct struct_TEST {
int size: 10; // Bit fields cannot be accessed
float arr[]; // Arrays of zero length cannot be accessed
};
- 在 C 语言中,无法直接访问 Go The language-defined structure type
对于枚举 enum
The underlying corresponding to the enumeration typeint
类型,Values of negative type are supported , 我们可以直接使用 C.xx 来进行访问
For example the enum type is :
enum TEST {
ONE,
TWO,
};
Using this type we can use c C.enum_TEST
When copying this variable,我们可以这样做:c = C.ONE
对于联合体 union
Go 语言中并不支持 C Language union type,They are converted to byte arrays of the corresponding size
例如
union B1 {
int i;
float f;
};
union B1
会被转换成为 4 个字节大小的 字节数组 [4]uint8
GO The operation union variable has 3 种方式:
- 在CHelper functions are defined in the language
- Go语言的
encoding/binary
Manually decode members**(Need to pay attention to the big endian little endian problem)** - 使用
unsafe
The package is cast to the corresponding type
举个例子
package main
/*
#include <stdint.h>
union TEST {
int i;
float f;
};
*/
import "C"
import (
"fmt"
"unsafe"
)
func main() {
var b C.union_TEST
*(*C.int)(unsafe.Pointer(&b)) = 1
fmt.Println("b.i:", *(*C.int)(unsafe.Pointer(&b)))
fmt.Println("b.f:", *(*C.float)(unsafe.Pointer(&b)))
}
When we read and write union variables,使用 unsafe
Package performance is the best,通过unsafe
获取指针,Then convert it to a pointer of the corresponding data type
参考资料:
欢迎点赞,关注,收藏
朋友们,你的支持和鼓励,是我坚持分享,提高质量的动力
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rnf9NE3P-1659626343417)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/0201d40a68894f2f825d2c66ea76ada1~tplv-k3u1fbpfcp-zoom-1.image)]
好了,本次就到这里
技术是开放的,我们的心态,更应是开放的.拥抱变化,向阳而生,努力向前行.
我是小魔童哪吒,欢迎点赞关注收藏,下次见~
边栏推荐
- 微擎盲盒交友变现-vp_ph打开慢优化
- 【实用软件】【VSCode】使用技巧大全(持续更新)
- OPPO Enco X2 迎来秋季产品升级 旗舰体验全面拉满
- Iridium Ruthenium Alloy/Iridium Oxide Biomimetic Nanozyme | Palladium Nanozyme | GMP-Pd Nanozyme | Gold-Palladium Composite Nanozyme | Ternary Metal Pd-M-Ir Nanozyme |shell nanozyme
- npm WARN config global `--global`, `--local` are deprecated. Use `--location=global` instead.
- Kyligence 通过 SOC 2 Type II 审计,以可信赖的企业级产品服务全球客户
- Implementation of graceful exit in Golang
- Demis Hassabis:AI 的强大,超乎我们的想象
- win7开机有画面进系统黑屏怎么办
- cordova installation error Command failed: powershell solution
猜你喜欢
【图像分类】2018-MobileNetV2
Web3中值得关注的基础设施
2019河北省大学生程序设计竞赛部分题题解
idea插件 协议 。。 公司申请软件用
组合导航精度分析
ACM MM 2022 统一归一化:加速Transformer工业部署的归一化方法
Ransom Letter Questions and Answers
Tf ferritin particles contain cisplatin / oxaliplatin / doxorubicin / methotrexate MTX / paclitaxel PTX and other drugs
echart 特例-多分组X轴
npm warn config global `--global`, `--local` are deprecated. use `--location=global` instead.
随机推荐
Auto.js中APP应用相关指令
In 2021 China industrial Internet security competition (competition) in fujian province and the first industry of fujian province Internet innovation competition
将视图模型转换为使用 Hilt 依赖注入
洛谷 P1629 邮递员送信 (三种最短路)
TortoiseSVN小乌龟的使用
npm warn config global `--global`, `--local` are deprecated. use `--location=global` instead.
Apple Font Lookup
C语言写数据库
XML小讲
爬虫基本原理介绍、实现以及问题解决
leetcode:45. 跳跃游戏II
LeetCode 1-10题
测试代码新的规则
[SemiDrive source code analysis] [MailBox inter-core communication] 51 - DCF_IPCC_Property implementation principle analysis and code combat
Apache DolphinScheduler 3.0.0 正式版发布!
【CMU博士论文】视频多模态学习:探索模型和任务复杂性,152页pdf
CMU博士论文 | 视频多模态学习:探索模型和任务复杂性
sklearn 笔记 TSNE
cordova installation error Command failed: powershell solution
Transferrin (TF) Modified Paclitaxel (PTX) Liposomes (TF-PTX-LP) | Transferrin (Tf) Modified Curcumin Liposomes