Вы записываете десять (ноль) байтов из GoPack.e
в packed.e
, который имеет тип char *
. Это не сработает, потому что указатели будут иметь размер 4 или 8 байтов в зависимости от вашей системы, поэтому даже если байты представляют действительный указатель, вы переполняете объем выделенной памяти.
Если вы хотите создать допустимая структура с допустимым полем packed.e
, вам нужно выделить 10 байтов памяти в куче C, скопировать байты в нее, а затем указать packed.e
на эту выделенную память. (Вам также потребуется освободить эту память, когда вы освободите соответствующую структуру packed
). Вы не можете сделать это напрямую с помощью binary.Write
.
Вы можете принять это как отправную точку:
buf := &bytes.Buffer{}
binary.Write(buf, binary.LittleEndian, g.a)
binary.Write(buf, binary.LittleEndian, g.b)
binary.Write(buf, binary.LittleEndian, g.c)
binary.Write(buf, binary.LittleEndian, g.d)
binary.Write(buf, binary.LittleEndian, uintptr(C.CBytes(g.e))
*out = *(*C.packed)(C.CBytes(buf.Bytes()))
Функция C.CBytes(b)
выделяет len(b)
байтов в C heap, и копирует в нее байты из b
, возвращая unsafe.Pointer
.
Обратите внимание, что я скопировал вашу строку *out = *(*C.packed)...
из вашего кода. Фактически это вызывает утечку памяти и ненужную копию. Вероятно, было бы лучше использовать модуль записи, который записывает байты непосредственно в память, на которую указывает out
.
Возможно, это?
const N = 10000 // should be sizeof(*out) or larger
buf := bytes.NewBuffer((*[N]byte)(unsafe.Pointer(out))[:])
Это делает bytes.Buffer
, который напрямую записывает в структуру out
без прохождения какой-либо промежуточной памяти. Обратите внимание, что из-за небезопасных махинаций это уязвимо для переполнения буфера, если вы напишете больше байтов данных, чем указано в out
.
Слова предупреждения: все это довольно неприятно, и те же проблемы, что и в C, и вам нужно будет проверить правила указателя cgo, чтобы убедиться, что вы не уязвимы для взаимодействий со сборкой мусора. Совет: учитывая, что вы говорите, что «не имеете большого опыта работы с указателями и распределением памяти», вам, вероятно, следует избегать написания или включения такого кода, потому что проблемы, которые он может вызвать, ужасны и могут быть не сразу очевидны *. 1033 *