Ganesh Rathinavel
Ganesh Rathinavel

Reputation: 1335

Translate a Go nested array of struct to C using CGO?

I am trying to create a struct, in Go, where one of it's children is an array of struct and then translate it to C using CGO.

I tried something like this in Go

*/
typedef struct FileInfo{
    int64_t Size;
    char *Name;
}FileInfo;

typedef struct Result{
    FileInfo **files;
}Result;

int64_t GetResult(void **presult, FileInfo **files) {
    Result *result = (Result *)malloc(sizeof(Result));
    result->files=files;

    *presult = result;

    int64_t ptr = (int64_t)result;

    return ptr;
}
*/
import "C"
func Run() {
    var arr []*C.struct_FileInfo

    ai := C.struct_FileInfo{
        Size: C.int64_t(1234),
        Name: C.CString("some name"),
    }

    arr = append(arr, &ai)

    var presult unsafe.Pointer
    ptr := C.GetResult(&presult, &arr[0])

    println("\nResult struct pointer: %v", ptr)
}

It threw an panic: runtime error: cgo argument has Go pointer to Go pointer error.

How to I fix this error?

Updates:

Working playground url: https://play.golang.org/p/vpLddEyY8kI

Upvotes: 0

Views: 512

Answers (1)

kostix
kostix

Reputation: 55443

The problem

  • arr is a slice of pointers (*C.struct_FileInfo).
  • &arr[0] takes the address of (a pointer to) the first element of that slice.
  • The ai variable, the address of which becomes the first element of arr, is allocated by Go.

Hence:

  • arr[0] contains &ai, which is a pointer to C.struct_FileInfo allocated by Go.
  • arr is also managed by Go and hence &arr[0] is "a Go pointer to Go pointer".

Please read this thoroughly.

Possible solution

One solution is to call C.malloc to allocate enough bytes to store a C.struct_FileInfo. This way, you will have Go pointer (&arr[0]) to C pointer, which is fine.

Don't forget to C.free it after you're done with that memory.

Upvotes: 2

Related Questions