Reputation: 522
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!
Upvotes: 1
Views: 11471
Reputation: 417552
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\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.
[]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[:])
Upvotes: 2