7

I am working with a C library that, unlike below, I do not control. I need to pass to a C function a pointer to an array that also contains pointers.

package main

/*
#include <stdio.h>

typedef int* pInt;

void foo(pInt p[]) {
  printf("foo()\n");
}
*/
import "C"
import "unsafe"

func main() {
    var i C.int
    var p1 C.pInt = (*C.int)(unsafe.Pointer(&i))
    var p2 C.pInt = (*C.int)(unsafe.Pointer(&i))
    var ps []C.pInt = []C.pInt{p1, p2}
    C.foo(unsafe.Pointer(&ps[0]))
}

This code results in the error panic: runtime error: cgo argument has Go pointer to Go pointer. I am wondering how I can rewrite the Go portion of this code so that it satisfies Cgo's pointer rules. My hope is that I can do this without having to write C helper code.

2
  • 1
    May I suggest you to post your question to the go-nuts mailing list? Cgo-related questions have a good chance to be answered there exactly by the people who tightened cgo rules in 1.6 (for good!) :-) Commented Mar 10, 2016 at 19:32
  • 1
    If you need to pass an array of pointers, you need to allocate the pointers in C, not Go. Commented Mar 10, 2016 at 19:48

2 Answers 2

7

Bad news, you have to define your helpers in C. Good news, well it's only 2 lines.

package main

/*
#include <stdlib.h> // for malloc/free
#include <stdio.h>

typedef int* pInt;

void foo(pInt p[]) { // you probably wanna pass a len to the function.
    *p[0] = 100;
    printf("foo()\n");
}

pInt * allocArray(size_t ln) { return (pInt*) malloc(ln * sizeof(pInt)); }
void freeArr(pInt * p) { free(p); }

*/
import "C"
import "unsafe"

func main() {
    var (
        i, sz  = 0, 2
        arr    = C.allocArray(C.size_t(sz))
        ps     = (*[100000]C.pInt)(unsafe.Pointer(arr))[:sz:sz]
        p1, p2 = (C.pInt)(unsafe.Pointer(&i)), (C.pInt)(unsafe.Pointer(&i))
    )
    ps[0], ps[1] = p1, p2
    C.foo(arr)
    C.freeArr(arr)
    println("i", i)
}
Sign up to request clarification or add additional context in comments.

Comments

5

Modifying OneOfOne's solution without the C helper functions, although it is nice to see how easy C helper functions are to write in the comments of the go file.

package main

/*
#include <stdio.h>

typedef int* pInt;

void foo(pInt p[]) { // you probably wanna pass a len to the function.
    *p[0] = 100;
    printf("foo()\n");
}

*/
import "C"
import "unsafe"

func main() {
    var (
        i, sz  = 0, 2
        arr    = (*C.pInt)(C.malloc(C.size_t(sz)))
        ps     = (*[100000]C.pInt)(unsafe.Pointer(arr))[:sz:sz]
        p1, p2 = (C.pInt)(unsafe.Pointer(&i)), (C.pInt)(unsafe.Pointer(&i))
    )
    ps[0], ps[1] = p1, p2
    C.foo(arr)
    C.free(unsafe.Pointer(arr))
    println("i", i)
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.