简体   繁体   English

Golang-结构,初始化和memcpy-正确的方法是什么?

[英]Golang - structs, initializing and memcpy - what is the proper way?

I'm new to Go and I wish to translate some C/C++ code I have to Go but I haven't been able to. 我是Go的新手,我希望翻译一些我必须去的C / C ++代码,但我还没有做到。 The problem resides in 2 places: how can I initialize a struct I've defined and how to do a "memcopy" 问题存在两个地方:如何初始化定义的结构以及如何执行“内存复制”

The code I'm talking about is this: http://play.golang.org/p/e8N255qEAk line 69 and 74. 我正在谈论的代码是这样的: http : //play.golang.org/p/e8N255qEAk第69和74行。

The C/C++ code I wanted to "translate" to Go is this: 我想“翻译”为Go的C / C ++代码是这样的:

            typedef char xchr;
            typedef int xint;
            typedef double xdob;
            typedef float xflt;
            typedef struct
            {
               xint p; 
               xdob lat_lon_ele[3];
               xflt psi_the_phi[3];
               xflt gear_flap_vect[3];
            }VEH1;

            avio.p = 0;
            avio.lat_lon_ele[0] = 47.460058;
            avio.lat_lon_ele[1] = -122.32104;
            avio.lat_lon_ele[2] = 8000.000;

            avio.psi_the_phi[0] = 110.5;
            avio.psi_the_phi[1] = 0.0;
            avio.psi_the_phi[2] = 0.0;

            avio.gear_flap_vect[0] = 1.0;
            avio.gear_flap_vect[1] = 0.0;
            avio.gear_flap_vect[2] = 0.0;

            VEH1* av = &avio;

            xchr data_send[6];
            data_send[0]='V';
            data_send[1]='E';
            data_send[2]='H';
            data_send[3]='1';
            data_send[4]=0;

            memcpy(&data_send[5],av,sizeof(VEH1)); // load in the data

The Go code looks like this: Go代码如下所示:

            type xchr int8
            type xint int
            type xdob float64
            type xflt float32

            type VEH1 struct {
                p              xint
                lat_lon_ele    [3]xdob
                psi_the_phi    [3]xflt
                gear_flap_vect [3]xflt
            }

            type VEHA struct {
                num_p xint

                lat_lon_ele    [10][3]xdob
                psi_the_phi    [10][3]xflt
                gear_flap_vect [10][3]xflt

                lat_view, lon_view, ele_view xdob
                psi_view, the_view, phi_view xflt
            }


            var avio VEH1
            avio = &VEH1{0, {47.460058, -122.32104, 8000.000}, {110.5, 0.0, 0.0}, {1.0, 0.0, 0.0}}

            data_send := [6]xchr{'V', 'E', 'H', '1', 0, 0}
            copy(data_send[5:5], avio);

Thank you! 谢谢!

So basically given these basic types: 因此,基本上给出了以下基本类型:

type xchr int8
type xint int
type xdob float64
type xflt float32

You want to copy the bytes (memory representation) of a value of the following struct type: 您要复制以下struct类型的值的字节(内存表示形式):

type VEH1 struct { // 52 bytes total
    p              xint    // 4 bytes (READ BELOW)
    lat_lon_ele    [3]xdob // 24 bytes
    psi_the_phi    [3]xflt // 12 bytes
    gear_flap_vect [3]xflt // 12 bytes
}

Note that the length of int in Go is platform dependent, it may be 32 bit or 64 bit depending on the target architecture you compile to. 请注意,Go中int的长度取决于平台,取决于您编译到的目标体系结构,它的长度可以是32位或64位。 That would lead to platform dependent behavior, so let's fix it to int32 for now: 这将导致平台相关的行为,所以现在让我们将其修复为int32

type xint int32

This is how the byte sizes of the above struct is calculated. 这就是上述struct的字节大小的计算方式。 If you need int64 , just change it and add 4 additional bytes in size calculation. 如果需要int64 ,只需对其进行更改并在大小计算中添加4个额外的字节。

Next you want the result in an array whose element types are xchr . 接下来,您需要将结果放入元素类型为xchr的数组中。 You need a big enough array, which is the "prefix" being "VEH1" followed by the data of the above struct . 您需要一个足够大的数组,即“前缀”为"VEH1"后跟上述struct的数据。 So it must have a size of 4+sizeof(VEH1) which is 56 . 因此它的大小必须为4+sizeof(VEH1) ,即56

In Go to copy the bytes of one type to the memory space of another type, you can do it the unsafe package and its general Pointer type. 在“将一种类型的字节复制到另一种类型的内存空间”中,您可以使用unsafe包及其通用Pointer类型来完成此操作。 Any pointer can be cast to unsafe.Pointer and unsafe.Pointer can be cast to any pointer type, so this is your "gateway" between different pointer types. 任何指针都可以unsafe.Pointer unsafe.Pointerunsafe.Pointerunsafe.Pointer可以unsafe.Pointer unsafe.Pointer为任何指针类型,因此这是您在不同指针类型之间的“网关”。

You can take the address of a struct value of VHE1 , convert it to Pointer , and convert the result Pointer to a pointer to the target data type. 您可以采用structVHE1的地址,将其转换为Pointer ,然后将结果Pointer转换为Pointer目标数据类型的指针。 Dereference the pointer and now you already have the value of the other type. 取消引用指针,现在您已经具有其他类型的值。

The builtin copy() can only be used with slices, so first you need to slice your data arrays to be able to pass them to copy() . 内置的copy()只能与sli​​ce一起使用,因此首先您需要对数据数组进行切片,以便将它们传递给copy()

You can do it like this: 您可以这样做:

avio := VEH1{0, [3]xdob{47.460058, -122.32104, 8000.000},
    [3]xflt{110.5, 0.0, 0.0}, [3]xflt{1.0, 0.0, 0.0}}
fmt.Printf("%+v\n", avio)

pavio := unsafe.Pointer(&avio)
pavio_arr := *((*[52]xchr)(pavio))

data_send := [56]xchr{'V', 'E', 'H', '1'}
n := copy(data_send[4:], pavio_arr[:])
fmt.Printf("Copied %d bytes\n", n)

fmt.Printf("%+v\n", data_send)

Output, wrapped to fit in screen: 包装成适合屏幕的输出:

{p:0 lat_lon_ele:[47.460058 -122.32104 8000] psi_the_phi:[110.5 0 0]
    gear_flap_vect:[1 0 0]}
Copied 52 bytes
[86 69 72 49 0 0 0 0 0 0 0 0 -81 33 56 46 -29 -70 71 64 77 45 91 -21 -117
    -108 94 -64 0 0 0 0 0 64 -65 64 0 0 -35 66 0 0 0 0 0 0 0 0 0 0 -128 63 0 0 0 0]

Try the working demo on the Go Playground . Go Playground上尝试运行的演示。

Having the result as []byte 结果为[]byte

If you want []byte result (eg you want to write the result to an io.Writer ), then use [56]byte type for data_send and of course cast pavio to *[52]byte : 如果您想要[]byte结果(例如,您要将结果写入io.Writer ),则对data_send使用[56]byte类型,当然将pavio*[52]byte

pavio := unsafe.Pointer(&avio)
pavio_arr := *((*[52]byte)(pavio))

data_send := [56]byte{'V', 'E', 'H', '1'}
n := copy(data_send[4:], pavio_arr[:])

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM