Go/CGo - how do you use a C array passed as a pointer

Sonia Hamilton picture Sonia Hamilton · Feb 12, 2013 · Viewed 8.7k times · Source

I'm posting this as a question/answer, as it took me a while to work out, and I wouldn't mind some feedback on my solution. In Go/CGo, how do you work with a C array passed as a pointer?

For example, with this C struct:

struct _GNetSnmpVarBind {                     
    guint32     *oid;       /* name of the variable */
    gsize       oid_len;    /* length of the name */
    ... and other fields
};  

I want to convert oid field to a Go string, how would I work with the guint32* pointer?

Answer

Nick Craig-Wood picture Nick Craig-Wood · Feb 12, 2013

You could convert the C array into a Go slice using a tip I saw in the go wiki

Untested but hopefully you get the idea! Don't let the slice live longer than the C data though as it points directly into it.

Last time I used this I had a look at the disassembly and it generates very efficient code.

func gIntArrayOidString(oid *_Ctype_guint32, oid_len _Ctype_gsize) (result string) {
    var oids []uint32
    sliceHeader := (*reflect.SliceHeader)((unsafe.Pointer(&oids)))
    sliceHeader.Cap = oid_len
    sliceHeader.Len = oid_len
    sliceHeader.Data = uintptr(unsafe.Pointer(oid))

    var result string
    for _, value := range oids {
        result += fmt.Sprintf(".%d", value)
    }
    return result[1:]
}