本教程操作环境:windows7系统、GO 1.18版本、Dell G3电脑。
c语言和golang是兼容的。你用c写的.c文件是可以被golang引用,直接使用的。
现代的各种高级的编程语言很多都是在C语言之上构建的,基本上也都能够调用C语言,并且这个在某些情况下也是有这个需求和存在的意义的。Go语言对这方面支持的挺不错,不光可以调用C语言,还能给C语言调用。这篇文章将对相关的内容做个说明。
(资料图片)
基础说明
Go语言工具包中有一个Cgo命令,它用来处理Go调用C相关操作。 我们可以直接使用该命令,也可以在运行或构建Go程序时自动调用它。【相关推荐:Go视频教程、编程教学】
Cgo对于C语言的处理本身是依赖系统中C语言相关的编译工具链的,所以需要注意对此的设置,主要是Go的环境变量设置:
特别需要注意的是Cgo需要使能,可以使用 go env -w CGO_ENABLED=1
命令来设置。上图中可以看到一些C编译时的FLAGS参数,如果有需要也可以进行相应设置调整。另外上面的 CC
CXX
是编译工具链的设置,也可以根据需求设置调整。
Go中调用C
Go中调用C语言最终在Go中都显示为名为 C
的伪包, 在Go中 import "C"
行之上以注释 #include ...
方式来引用C语言相关的库。这些被引用的库中公共的变量和函数等在Go中会被挂到 C
包中以供使用。下面是个简单的演示:
在Go中调用C只要上面这样就行了,使用起来还是很方便的。
通常来说C语言程序的项目中除了C语言代码外可能还有汇编代码;或者项目也有可能是C/C++混合编程的。这些项目都可以在Go中使用,Cgo会自动识别后缀为 .c
.s
.S
.sx
.cc
.cpp
.cxx
的文件,并调用对应的编译器去编译。
需要注意的是C++中的重载和类方法等C不支持的语法想要在Go中使用都需要用C语言标准函数包装一层,使用方法就和C语言中调用C++一样。
C中调用Go
下面测试中如果有问题可以尝试 go clean
重置项目后再进行。
Go的函数可以导出给C用,只要在要导出的函数前面加上 //export funcname
就行了,然后可以使用 go build -buildmode=c-shared -o libxxx.so
命令编译生成动态库和头文件供C语言中使用:
另外也可以使用 go build -buildmode=c-archive -o libxxx.a
编译生成可用C语言使用的静态库。
数据类型差异
两个语言间调用其实就是数据的传递处理,需要注意的是因为两者毕竟不是同一种语言所以两者之间可以交互的数据类型是有限制的。有些时候也会有强制转换数据类型的需求,比如下面这个代码:
package rand// #include import "C"func Random() int { return int(C.random()) // C函数返回值给Go,random的返回值是long类型}func Seed(i int) { C.srandom(C.uint(i)) // Go传值给C的函数,srandom函数接收uint类型数据}
登录后复制
两者间可用的基本数值类型转换有下面一些:
C.char, C.schar (signed char), C.uchar (unsigned char)C.short, C.ushort (unsigned short)C.int, C.uint (unsigned int)C.long, C.ulong (unsigned long)C.longlong (long long), C.ulonglong (unsigned long long)C.float, C.doubleC.complexfloat (complex float), C.complexdouble (complex double)
登录后复制
除了上面的基础类型,指针也是可以传递的。特别的C语言中的 void*
指针相当于Go中的 unsafe.Pointer
。
C中的 __int128_t
和 __uint128_t
相当于Go中的 [16]byte
。
C中函数传输参数为数组的话直接传递数组名就行,在Go中向这类函数传递数组需要传递数组第一个元素的地址,另外需要注意的是数组中元素也必须是C语言中支持的类型:
C.f(&C.arr[0])
登录后复制
C中并没有string类型,使用字符串时需要进行处理:
package print// #include // #include import "C"import "unsafe"func Print(s string) { cs := C.CString(s) // 这个方式会将字符串拷贝一份,返回指针,注意使用完需要释放内存 defer C.free(unsafe.Pointer(cs)) // defer修饰的语句会在该函数退出前执行 C.fputs(cs, (*C.FILE)(C.stdout))}
登录后复制
另外C语言的字符串 *C.char
可以使用 C.GoString()
转换成Go中的字符串。
C中的 struct
union
enum
这些类型在Go使用需要加上对应的前缀,变成 struct_xxx
union_xxx
enum_xxx
。其中联合体在Go中将成为字节数组的形式。这些对象的成员名如果和Go的关键词一样的话,在Go中使用需要在成员名前面加下划线,比如 x._name
。
C中的 sizeof
在Go中需要使用 C.sizeof_T
方式使用,T是变量数据类型。
更多编程相关知识,请访问:编程视频!!
以上就是go语言兼容c语言吗的详细内容,更多请关注php中文网其它相关文章!