0

I'm trying to convert this c++ to go.

This is in short what the c code is doing:

static const char *pSharedMem = NULL;
int sessionInfoOffset;

return pSharedMem + pHeader->sessionInfoOffset;

This is my (pseudo) go code:

var pSharedMem unsafe.Pointer
sessionInfoLen C.int

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

I've never really written any C code and I have no idea if this a good way of retrieving a byte slice from an unsafe.Pointer. Could go anything wrong with this (copying wrong piece of memory or something) and is this performant of am I doing something really stupid?

Leon
  • 841
  • 3
  • 10
  • 21
  • If `pSharedMem` comes from cgo, then yes, that is correct, and yes, it is performant, but [it will copy memory](https://github.com/golang/go/blob/25bf792197ff737fc84c8b1dd46be8a6b066333a/src/runtime/string.go#L312-L320), so you can't write to the new byte slice and expect the underlying C array to change. If you have to change the original C array. you could use `reflect.SliceHeader` and an `unsafe.Pointer`-based `*[]byte` cast. This won't do a copy, but is less safe. – andlabs Mar 21 '15 at 22:55
  • Though are you rewriting the library entirely, or simply writing a bindings package? If you're doing a full rewrite, would you not be able to get rid of the C code entirely (and thus should choose a different approach to implementing `irsdk_header`)? `pSharedMem` appears to come from a memory-mapped file, and there are several mmap packages for Go (as well as `syscall.Mmap()`)... – andlabs Mar 21 '15 at 22:57
  • Thanks! Copying isn't bad because the memory-mapped file could change 60 times a second. So when copying it I have time to process the data. I would love to get rid of cgo but I don't know how. The memory-mapped file is provided by an external (closed source) process with a specific layout. I thought if I wouldn't use C.int's the memory wouldn't map correctly to the struct. I could be wrong because of my lack of understanding this stuff... – Leon Mar 22 '15 at 13:12

1 Answers1

1

GoBytes is going to be the safest method. You still have to ensure that the array exists for the entirety of the copy operation, but once you have the bytes copied, you know it can't be changed from cgo. As long as the memory being copied isn't too large, or the copy presents a performance problem, this is the way to go.

If you want direct access to the bytes via a slice, you can slice it as an array like so:

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

This saves you the copy, but you then have to manage concurrent access from cgo, and ensure the memory isn't released while you're accessing it from Go.

JimB
  • 104,193
  • 13
  • 262
  • 255