1

I have a use-case where C code will call Go function (exported by building Go as shared library). All this is in 64bit Linux.

The C code allocates a char* buffer and passes it to the Go function. The Go code is expected to fill the buffer.

The receiving Go code is like:

//export FillBuf
func FillBuf(p uintptr, sz int) {
   dest := toslice(p, sz)
   // Copy into dest
}

The C code is like:

(Note: The type GoUintptr is defined in auto-generated header by Go compiler)

char buf[100];
FillBuf((GoUintptr) &buf[0], 100);

I have the following Go code which "wraps" the C buffer into a Go slice:

func toslice(ptr uintptr, sz int) []byte {
    h := reflect.SliceHeader{
        Data: ptr,
        Len:  sz,
        Cap:  sz,
    }
    buf := *(*[]byte)(unsafe.Pointer(&h))
    return buf
}

My understanding is that the Go will not GC the C buffer because it keeps track of the addresses it has allocated and C buffer is not among them.

Questions are:

  1. Is this safe? (I think it should be but not sure)
  2. Is this the only way? (The function signatures cannot be changed)
bitflood
  • 441
  • 5
  • 15
  • https://github.com/golang/go/wiki/cgo#turning-c-arrays-into-go-slices – JimB May 22 '20 at 18:45
  • If I understood correctly the line in the above link `(*[1 << 28]C.YourType)(unsafe.Pointer(theCArray))[:length:length]` is creating a fixed size array (typecasting actually) and then slicing it to create the slice. – bitflood May 22 '20 at 18:57
  • See https://stackoverflow.com/questions/48756732/what-does-1-30c-yourtype-do-exactly-in-cgo – JimB May 22 '20 at 19:44

0 Answers0