cgo类型转换(一)

Cgo总结(一)

这篇文章的目的:
探究c的基本类型到go类型的转换怎样才能安全;下面是根据之间的转换做的测试
结论是:
坑真多,自己要小心点;运行速度还慢,能不用就尽量不用!
测试内容如下:

1.基本转换

C类型调用方法Go类型字节数(byte)数值范围
charC.charbyte1-128~127
signed charC.scharint81-128~127
unsigned charC.ucharuint810~255
short intC.shortint162-32768~32767
short unsigned intC.ushortuint1620~65535
intC.intint4-2147483648~2147483647
unsigned intC.uintuint3240~4294967295
long intC.longint32 or int644-2147483648~2147483647
long unsigned intC.ulonguint32 or uint6440~4294967295
long long intC.longlongint648-9223372036854776001~9223372036854775999
long long unsigned intC.ulonglonguint6480~18446744073709552000
floatC.floatfloat324-3.4E-38~3.4E+38
doubleC.doublefloat6481.7E-308~1.7E+308
wchar_tC.wchar_twchar_t20~65535
void *unsafe.Pointer
1.1 char —>byte
package main
/*
#include<stdio.h>
char a = -128;
*/
import "C"
import (
"fmt"
"reflect"
)

func main() {
	b := byte(C.a)
	fmt.Println(C.a)
	fmt.Println("类型为:",reflect.TypeOf(C.a))
	fmt.Println(b)
	fmt.Println("类型为:",reflect.TypeOf(b))
}

结果:

-128
类型为: main._Ctype_schar
128
类型为: uint8

代码2:

package main
/*
#include<stdio.h>
 char  a = -127;
*/
import "C"
import (
"fmt"
"reflect"
)

func main() {
	b := int8(C.a)
	fmt.Println(C.a)
	fmt.Println("类型为:",reflect.TypeOf(C.a))
	fmt.Println(b)
	fmt.Println("类型为:",reflect.TypeOf(b))
}

结果为:

-127
类型为: main._Ctype_char
-127
类型为: int8

由上面看出byte 跟uint8的功能一样,问题是为啥有byte的存在呢?

1.2 signed char—>int8
package main
/*
#include<stdio.h>
signed char a = 12;
*/
import "C"
import (
	"fmt"
	"reflect"
)

func main() {
	b := byte(C.a)
	fmt.Println(C.a)
	fmt.Println("类型为:",reflect.TypeOf(C.a))
	fmt.Println(b)
	fmt.Println("类型为:",reflect.TypeOf(b))
}

结果:

12
类型为: main._Ctype_schar
12
类型为: uint8
1.3 unsigned char---->uint8
package main
/*
#include<stdio.h>
 unsigned char a = 254;
*/
import "C"
import (
"fmt"
"reflect"
)

func main() {
	b := byte(C.a)
	fmt.Println(C.a)
	fmt.Println("类型为:",reflect.TypeOf(C.a))
	fmt.Println(b)
	fmt.Println("类型为:",reflect.TypeOf(b))
}

结果为:

254
类型为: main._Ctype_uchar
254
类型为: uint8
1.4 short int ----->int16
package main
/*
#include<stdio.h>
 short a = -32768;
*/
import "C"
import (
"fmt"
"reflect"
)

func main() {
	b := int16(C.a)
	fmt.Println(C.a)
	fmt.Println("类型为:",reflect.TypeOf(C.a))
	fmt.Println(b)
	fmt.Println("类型为:",reflect.TypeOf(b))
}

结果:

-32768
类型为: main._Ctype_short
-32768
类型为: int16
1.5 short unsigned int ---->uint16
package main
/*
#include<stdio.h>
 short unsigned int  a = 65535;
*/
import "C"
import (
"fmt"
"reflect"
)

func main() {
	b := uint16(C.a)
	fmt.Println(C.a)
	fmt.Println("类型为:",reflect.TypeOf(C.a))
	fmt.Println(b)
	fmt.Println("类型为:",reflect.TypeOf(b))
}

结果:

65535
类型为: main._Ctype_ushort
65535
类型为: uint16
1.6 int —> int
package main
/*
#include<stdio.h>
 int  a = -2147483648;
*/
import "C"
import (
"fmt"
"reflect"
)

func main() {
	b := int(C.a)
	fmt.Println(C.a)
	fmt.Println("类型为:",reflect.TypeOf(C.a))
	fmt.Println(b)
	fmt.Println("类型为:",reflect.TypeOf(b))
}

结果为:

-2147483648
类型为: main._Ctype_int
-2147483648
类型为: int
1.7 unsigned int ----->uint32
package main
/*
#include<stdio.h>
 unsigned int  a = 4294967295;
*/
import "C"
import (
"fmt"
"reflect"
)

func main() {
	b := uint32(C.a)
	fmt.Println(C.a)
	fmt.Println("类型为:",reflect.TypeOf(C.a))
	fmt.Println(b)
	fmt.Println("类型为:",reflect.TypeOf(b))
}

结果:

4294967295
类型为: main._Ctype_uint
4294967295
类型为: uint32
1.8 long int —>int32 or int64
package main
/*
#include<stdio.h>
 long int  a = 2147483647;
*/
import "C"
import (
"fmt"
"reflect"
)

func main() {
	b := uint32(C.a)
	c := uint64(C.a)
	fmt.Println(C.a)
	fmt.Println("类型为:",reflect.TypeOf(C.a))
	fmt.Println(b)
	fmt.Println("类型为:",reflect.TypeOf(b))
	fmt.Println(c)
	fmt.Println("类型为:",reflect.TypeOf(c))
}

结果:

2147483647
类型为: main._Ctype_long
2147483647
类型为: uint32
2147483647
类型为: uint64
1.9 long unsigned int----->uint32 or uint64
package main
/*
#include<stdio.h>
 long unsigned int  a = 4294967295;
*/
import "C"
import (
"fmt"
"reflect"
)

func main() {
	b := uint32(C.a)
	c := uint64(C.a)
	fmt.Println(C.a)
	fmt.Println("类型为:",reflect.TypeOf(C.a))
	fmt.Println(b)
	fmt.Println("类型为:",reflect.TypeOf(b))
	fmt.Println(c)
	fmt.Println("类型为:",reflect.TypeOf(c))
}
2.0 long long int ----->int64
package main
/*
#include<stdio.h>
 long long int  a = -9223372036854776001;
*/
import "C"
import (
"fmt"
"reflect"
)

func main() {
	b := int32(C.a)
	c := int64(C.a)
	fmt.Println(C.a)
	fmt.Println("类型为:",reflect.TypeOf(C.a))
	fmt.Println(b)
	fmt.Println("类型为:",reflect.TypeOf(b))
	fmt.Println(c)
	fmt.Println("类型为:",reflect.TypeOf(c))
}

结果:

9223372036854775615
类型为: main._Ctype_longlong
-193
类型为: int32
9223372036854775615
类型为: int64

只有int64能接收到

2.1 long long unsigned int —> uint64
package main
/*
#include<stdio.h>
 long long unsigned int  a = -9223372036854776001;
*/
import "C"
import (
"fmt"
"reflect"
)

func main() {
	b := uint32(C.a)
	c := uint64(C.a)
	fmt.Println(C.a)
	fmt.Println("类型为:",reflect.TypeOf(C.a))
	fmt.Println(b)
	fmt.Println("类型为:",reflect.TypeOf(b))
	fmt.Println(c)
	fmt.Println("类型为:",reflect.TypeOf(c))
}

结果为:

9223372036854775615
类型为: main._Ctype_ulonglong
4294967103
类型为: uint32
9223372036854775615
类型为: uint64

只有uint64能接收到

2.2 float---->float32
package main
/*
#include<stdio.h>
 float  a = -3.14;
*/
import "C"
import (
"fmt"
"reflect"
)

func main() {
	b := float32(C.a)
	fmt.Println(C.a)
	fmt.Println("类型为:",reflect.TypeOf(C.a))
	fmt.Println(b)
	fmt.Println("类型为:",reflect.TypeOf(b))
}

结果为:

类型为: main._Ctype_float
-3.14
类型为: float32
2.3 double—>float64
package main
/*
#include<stdio.h>
 double  a = -3.14159267333333333333333;
*/
import "C"
import (
"fmt"
"reflect"
)

func main() {
	b := float32(C.a)
	c := float64(C.a)
	fmt.Println(C.a)
	fmt.Println("类型为:",reflect.TypeOf(C.a))
	fmt.Println(b)
	fmt.Println("类型为:",reflect.TypeOf(b))
	fmt.Println(c)
	fmt.Println("类型为:",reflect.TypeOf(c))
}

结果为:

-3.1415926733333333
类型为: main._Ctype_double
-3.1415927
类型为: float32
-3.1415926733333333
类型为: float64
2.5 void * ---->*
package main
/*
#include<stdio.h>
 int  *a = 65535;
 void *p =&a;
 void printpoint(){
 printf("point:%p\n",p);
 }
*/
import "C"
import (
"fmt"
"reflect"
"unsafe"
)

func main() {
	b := unsafe.Pointer(C.p)
	fmt.Println(C.p)
	fmt.Println("类型为:",reflect.TypeOf(C.a))
	fmt.Println(b)
	fmt.Println("类型为:",reflect.TypeOf(b))
	fmt.Println(C.printpoint())
}

结果:

0x53ec28
类型为: *main._Ctype_int
0x53ec28
类型为: unsafe.Pointer
[]
point:000000000053EC28

由以上看出从c到go的指针还是一样

总结:

​ 在使用过程中转数据经常会造成数据不准的情况,查的时候特别费精力, 在 C 中的整形比如 int 在标准中是没有定义具体字长的,但一般默认是 4 字节,对应 CGO 类型中 C.int 则明确定义了字长是 4 ,但 golang 中的 int 字长则是 8 ,因此对应的 golang 类型不是 int 而是 int32 。为了避免go在调用C的时候还要考虑复杂的类型,建议使用 C99 标准的数值类型,对应的转换关系如下:

C语言类型CGO类型Go语言类型
int8_tC.int8_tint8
uint8_tC.uint8_tuint8
int16_tC.int16_tint16
uint16_tC.uint16_tuint16
int32_tC.int32_tint32
uint32_tC.uint32_tuint32
int64_tC.int64_tint64
uint64_tC.uint64_tuint64

代码:

package main
/*
#include <stdint.h>
 int8_t a = -128;
 uint8_t b= 255;
 int16_t c= -32768;
 uint16_t d= 65535;
 int32_t e = -2147483648;
 uint32_t f = 4294967295;
 int64_t g = -9223372036854776001;
 uint64_t h = 9223372036854775999;
*/
import "C"
import (
"fmt"
"reflect"
)

func main() {
	fmt.Println("---------------int8-------------")
	a1 := int8(C.a)
	fmt.Println(C.a)
	fmt.Println(a1)
	fmt.Println("类型为:",reflect.TypeOf(C.a))
	fmt.Println("转后的类型:",reflect.TypeOf(a1))
	fmt.Println("---------------uint8-------------")
	b1 := uint8(C.b)
	fmt.Println(C.b)
	fmt.Println(b1)
	fmt.Println("类型为:",reflect.TypeOf(C.b))
	fmt.Println("转后的类型:",reflect.TypeOf(b1))

	fmt.Println("---------------int16-------------")
	c1 := int16(C.c)
	fmt.Println(C.c)
	fmt.Println(c1)
	fmt.Println("类型为:",reflect.TypeOf(C.c))
	fmt.Println("转后的类型:",reflect.TypeOf(c1))
	fmt.Println("---------------uint16-------------")
	d1 := uint16(C.d)
	fmt.Println(C.d)
	fmt.Println(d1)
	fmt.Println("类型为:",reflect.TypeOf(C.d))
	fmt.Println("转后的类型:",reflect.TypeOf(d1))

	fmt.Println("---------------int32-------------")
	e1 := int32(C.e)
	fmt.Println(C.e)
	fmt.Println(e1)
	fmt.Println("类型为:",reflect.TypeOf(C.e))
	fmt.Println("转后的类型:",reflect.TypeOf(e1))
	fmt.Println("---------------uint32-------------")
	f1 := uint32(C.f)
	fmt.Println(C.f)
	fmt.Println(f1)
	fmt.Println("类型为:",reflect.TypeOf(C.f))
	fmt.Println("转后的类型:",reflect.TypeOf(f1))

	fmt.Println("---------------int64-------------")
	g1 := int64(C.g)
	fmt.Println(C.g)
	fmt.Println(g1)
	fmt.Println("类型为:",reflect.TypeOf(C.g))
	fmt.Println("转后的类型:",reflect.TypeOf(g1))
	fmt.Println("---------------uint64-------------")
	h1 := uint64(C.h)
	fmt.Println(C.h)
	fmt.Println(h1)
	fmt.Println("类型为:",reflect.TypeOf(C.h))
	fmt.Println("转后的类型:",reflect.TypeOf(h1))
}

结果:

---------------int8-------------
-128
-128
类型为: main._Ctype_int8_t
转后的类型: int8
---------------uint8-------------
255
255
类型为: main._Ctype_uint8_t
转后的类型: uint8
---------------int16-------------
-32768
-32768
类型为: main._Ctype_int16_t
转后的类型: int16
---------------uint16-------------
65535
65535
类型为: main._Ctype_uint16_t
转后的类型: uint16
---------------int32-------------
-2147483648
-2147483648
类型为: main._Ctype_int32_t
转后的类型: int32
---------------uint32-------------
4294967295
4294967295
类型为: main._Ctype_uint32_t
转后的类型: uint32
---------------int64-------------
9223372036854775615
9223372036854775615
类型为: main._Ctype_int64_t
转后的类型: int64
---------------uint64-------------
9223372036854775999
9223372036854775999
类型为: main._Ctype_uint64_t
转后的类型: uint64

以上都是很简单的,只是作为探究C和go数据之间转换的了解;送人玫瑰,手留余香!!!
参考:
https://blog.csdn.net/darlingtangli/article/details/84198859

  • 6
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值