CGO Types
C作為一種混合編程語言已經很久了,無論那些廣泛使用的包是用何種語言實現的,都導出了和C兼容的API。Go程序調用C程序,可以借助兩種工具實現,一種是cgo,另一種是SWIG工具。Cgo是為C函數創建go綁定的工具;SWIG工具可以提供更復雜的特性來調用C++程序。(關於SWIG工具的使用,可以參考以前的《calling c++ from golang with swig 》系列隨筆)。
本文主要講述C語言類型、在CGO中可以引用的C類型及對應的引用類型名稱。
查詢C99標准文檔(6.2.5 Types),主要類型包括:_Bool、char、signed char、unsigned char、short、unsigned short、int、unsigned int、long、unsigned long、long long、unsigned long long、float、double、long double、float _Complex、double _Complex、long double _Complex、void *、__int128_t、__uint128_t
在CGO中引用C類型的名稱可以參考CGO官方文檔(Command cgo)。Go references to C 部分給出了可以引用的數值類型名稱。
綜合兩份參考文獻,給出下面的類型列表。
C Types |
Cgo Types |
_Bool |
C._Bool |
char |
C.char |
signed char |
C.schar |
unsigned char |
C.uchar |
short |
C.short |
unsigned short |
C.ushort |
int |
C.int |
unsigned int |
C.uint |
long |
C.long |
unsigned long |
C.ulong |
long long |
C.longlong |
unsigned long long |
C.ulonglong |
float |
C.float |
double |
C.double |
long double |
不支持(unexpected: 16-byte float type - long double) |
float _Complex |
C.complexfloat |
double _Complex |
C.complexdouble |
long double _Complex |
不支持( unexpected: 32-byte complex type - complex long double) |
void* |
unsafe.Pointer |
__int128_t |
[16]byte |
__uint128_t |
[16]byte |
C語言中的數值類型long double和long double _Complex在CGO中不能引用,編譯報錯。
寫一個簡單的程序來演示下:
package main /* #include <limits.h> #include <float.h> _Bool b = 1; char c = 'A'; signed char sc = CHAR_MIN; unsigned char usc = UCHAR_MAX; short s = SHRT_MIN; unsigned short us = USHRT_MAX; int i = INT_MIN; unsigned int ui = UINT_MAX; long l = LONG_MIN; unsigned long ul = ULONG_MAX; long long ll = LONG_LONG_MIN; unsigned long long ull = ULONG_LONG_MAX; float f = FLT_MIN; double d = DBL_MIN; long double ld = LDBL_MIN; float _Complex fc = 5+5i; double _Complex dc = 5+5i; long double _Complex ldc = 5+5i; __int128_t i128 = 0; __uint128_t ui128 = 3.4028236692093846346337460743177e+38; void *ptr = 0; */ import "C" import "fmt" import "unsafe" func main() { fmt.Println(C.b) fmt.Println(C.c) fmt.Println(C.sc) fmt.Println(C.usc) fmt.Println(C.s) fmt.Println(C.us) fmt.Println(C.i) fmt.Println(C.ui) fmt.Println(C.l) fmt.Println(C.ul) fmt.Println(C.ll) fmt.Println(C.ull) fmt.Println(C.f) fmt.Println(C.d) //fmt.Println(C.ld) fmt.Println(C.fc) fmt.Println(C.dc) //fmt.Println(C.ldc) fmt.Println(C.i128) fmt.Println(C.ui128) fmt.Println(C.ptr) fmt.Println("-------------------------------------------------") fmt.Println(C._Bool(true)) fmt.Println(C.char('A')) fmt.Println(C.schar(-128)) fmt.Println(C.uchar(255)) fmt.Println(C.short(C.SHRT_MIN)) fmt.Println(C.ushort(C.USHRT_MAX)) fmt.Println(C.int(C.INT_MIN)) fmt.Println(C.uint(C.UINT_MAX)) fmt.Println(C.long(C.LONG_MIN)) fmt.Println(C.ulong(C.ULONG_MAX)) fmt.Println(C.longlong(C.LONG_LONG_MIN)) fmt.Println(C.ulonglong(18446744073709551615)) fmt.Println(C.float(-1)) fmt.Println(C.double(-1)) //fmt.Println(C.longdouble(1)) fmt.Println(C.complexfloat(5 + 5i)) fmt.Println(C.complexdouble(5 + 5i)) C.i128 = [16]byte{15: 127} fmt.Println(C.i128) C.ui128 = [16]byte{15: 255} fmt.Println(C.ui128) C.ptr = unsafe.Pointer(nil) fmt.Println(C.ptr) }
運行后,輸出結果如下:(運行環境:Windows 7 64位操作系統,go version go1.8.3 windows/amd64)
true 65 -128 255 -32768 65535 -2147483648 4294967295 -2147483648 4294967295 -9223372036854775808 18446744073709551615 1.1754944e-38 2.2250738585072014e-308 (5+5i) (5+5i) [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0] [255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255] <nil> ------------------------------------------------- true 65 -128 255 -32768 65535 -2147483648 4294967295 -2147483648 4294967295 -9223372036854775808 18446744073709551615 -1 -1 (5+5i) (5+5i) [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127] [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255] <nil>