dragon8837 2015-06-18 07:16
浏览 187
已采纳

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

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. 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.

The C/C++ code I wanted to "translate" to Go is this:

            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:

            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!

  • 写回答

1条回答 默认 最新

  • donglu9743 2015-06-18 07:57
    关注

    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:

    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. That would lead to platform dependent behavior, so let's fix it to int32 for now:

    type xint int32
    

    This is how the byte sizes of the above struct is calculated. If you need int64, just change it and add 4 additional bytes in size calculation.

    Next you want the result in an array whose element types are xchr. You need a big enough array, which is the "prefix" being "VEH1" followed by the data of the above struct. So it must have a size of 4+sizeof(VEH1) which is 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. 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.

    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. 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().

    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
    ", 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)
    
    fmt.Printf("%+v
    ", 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.

    Having the result as []byte

    If you want []byte result (e.g. 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:

    pavio := unsafe.Pointer(&avio)
    pavio_arr := *((*[52]byte)(pavio))
    
    data_send := [56]byte{'V', 'E', 'H', '1'}
    n := copy(data_send[4:], pavio_arr[:])
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥30 关于用python写支付宝扫码付异步通知收不到的问题
  • ¥50 vue组件中无法正确接收并处理axios请求
  • ¥15 隐藏系统界面pdf的打印、下载按钮
  • ¥15 MATLAB联合adams仿真卡死如何解决(代码模型无问题)
  • ¥15 基于pso参数优化的LightGBM分类模型
  • ¥15 安装Paddleocr时报错无法解决
  • ¥15 python中transformers可以正常下载,但是没有办法使用pipeline
  • ¥50 分布式追踪trace异常问题
  • ¥15 人在外地出差,速帮一点点
  • ¥15 如何使用canvas在图片上进行如下的标注,以下代码不起作用,如何修改