2015-03-21 2 views
0

Я пытаюсь преобразовать this c++ в go.Каков наилучший (самый безопасный + наиболее эффективный) способ получения определенного фрагмента байтов из небезопасного.Pointer

Это вкратце то, что делает с код:

static const char *pSharedMem = NULL; 
int sessionInfoOffset; 

return pSharedMem + pHeader->sessionInfoOffset; 

Это мой (псевдо) идти код:

var pSharedMem unsafe.Pointer 
sessionInfoLen C.int 

byteSlice := C.GoBytes(pSharedMem, pHeader.sessionInfoLen) 
return byteSlice[pHeader.sessionInfoOffset:] 

Я действительно никогда не написал никакого кода C и у меня есть не знаю, если это хороший способ получить байтовый фрагмент из небезопасного. Поинтер. Не могли бы вы пойти с этим неправильно (копировать неправильную память или что-то в этом роде) и является ли это исполнением того, что я делаю что-то действительно глупое?

+0

Если 'pSharedMem' исходит из cgo, то да, это правильно, и да, оно выполнено, но [скопирует память] (https://github.com/golang/go/blob/25bf792197ff737fc84c8b1dd46be8a6b066333a/src /runtime/string.go#L312-L320), поэтому вы не можете писать в новый байтовый фрагмент и ожидать, что базовый массив C изменится. Если вам нужно изменить исходный массив C. вы можете использовать 'reflect.SliceHeader' и' 'unsafe.Pointer''' [] byte' cast. Это не сделает копию, но менее безопасно. – andlabs

+0

Хотя вы полностью переписываете библиотеку или просто записываете пакет привязок? Если вы полностью переписываете, не могли бы вы полностью избавиться от кода C (и, следовательно, выбрать другой подход к реализации «irsdk_header»)? 'pSharedMem', похоже, поступает из файла с отображением памяти, и есть несколько пакетов mmap для Go (а также' syscall.Mmap() ') ... – andlabs

+0

Спасибо! Копирование не является плохим, потому что файл с отображением памяти может меняться 60 раз в секунду. Поэтому при копировании у меня есть время для обработки данных. Я бы хотел избавиться от кого, но я не знаю, как это сделать. Файл с отображением памяти предоставляется внешним (закрытым исходным) процессом с определенным макетом. Я думал, что если я не буду использовать C.int, то память не будет правильно отображаться в структуре. Я могу ошибаться из-за того, что я не понимаю этого материала ... – Leon

ответ

1

GoBytes будет самым безопасным методом. Вы все равно должны убедиться, что массив существует для всей операции копирования, но как только вы скопировали байты, вы знаете, что он не может быть изменен из cgo. Пока копия памяти не слишком велика или копия представляет проблему с производительностью, это путь.

Если вы хотите прямой доступ к байтам через кусочек, вы можете нарезать его как массив так:

size := pHeader.sessionInfoLen 
byteSlice := (*[1<<30]byte)(pSharedMem)[:size:size] 

Это экономит копию, но затем вы должны управлять параллельным доступом с ОЦП, и убедитесь, что память не выпущена, когда вы обращаетесь к ней с Go.

Смежные вопросы