I have a c union that stores my data as part of a value struct
union data_union {
char *string_val;
int8_t int8_val;
int64_t int64_val;
// so on
};
typedef enum {
MY_STRING,
MY_INT8,
MY_INT64,
// so on
} data_type;
struct value_struct {
data_type type;
data_union data;
}
if I want to read an int8 value from c into go i use
int8_val := *(*C.int8_t)(unsafe.Pointer(&(cValue.data[0])))
goInt := int64(int8_val)
similarly for a int64 value
int64_val := *(*C.int64_t)(unsafe.Pointer(&(cValue.data[0])))
goInt := int64(int64_val)
how do i read a char * null terminated string ?
i am doing the following and I am getting garbage values
string_val := C.GoString((*C.char)(unsafe.Pointer(&(cValue.data[0]))))
I have tried to cast to single characters, but to no avail
var cString []byte
ptr := unsafe.Pointer(&(cValue.data[0]))
for {
char := *(*C.char)(ptr)
if char == 0 {
break
}
cString = append(cString, byte(char))
ptr = unsafe.Pointer(uintptr(ptr) + unsafe.Sizeof(char))
}
goString := string(cString)
and I have tried to cast to unsafe.Slice, but honestly I don't get it, and it doesn't work
cStringPtr := (*byte)(unsafe.Pointer(&(cValue.data[0])))
cString := unsafe.Slice(cStringPtr, 0)
// Convert the byte slice to a Go string
goString := string(cString)
After a bit of tinkering I realized that I could just return a
char *from a C function on the C side of thingsand then the conversion on the go side is simple
still looking for a better way though, since I have a lot of entries in my union and I don't want to pollute my go code with wrappers to wrappers in a project where the whole thing was a wrapper to a c api in the first place.