CGo: syntax for array of uints/pointer to uint

908 views
Skip to first unread message

Sonia Hamilton

unread,
Jan 24, 2013, 10:03:28 PM1/24/13
to golan...@googlegroups.com
Using CGo, how would I access an array of unsigned ints, when I'm passed
a pointer to an unsigned int?

ie in C I would do this (using the equivalence of arrays and pointers):

> for (i = 0; i < arr_len; i++) {
> printf(".%u", arr[i]);
> }

My Go equivalent is dying as I'm using the wrong syntax:

> for i := 0; i < arr_len; i++ {
> fmt.Printf(".%d", arr[i])
> }
>
> invalid operation: arr[i] (index of type *_Ctype_uint)

(this is for converting an SNMP OID that's in an array of uint's to a
string. I know about C's "unsigned int" being call C.uint in Go).

--
Sonia Hamilton
http://www.snowfrog.net
Message has been deleted

Andy Balholm

unread,
Jan 24, 2013, 11:33:42 PM1/24/13
to golan...@googlegroups.com
If you know the length of the array at compile time, cast the pointer to an array type:

arr1 := (*[6]C.uint)arr

If you don't know the length at compile time, your options would be using pointer arithmetic or using runtime.SliceHeader to create a slice.

minux

unread,
Jan 25, 2013, 5:21:54 AM1/25/13
to Kevin Gillette, golan...@googlegroups.com

On Fri, Jan 25, 2013 at 11:27 AM, Kevin Gillette <extempor...@gmail.com> wrote:
If the length of the C array is invariant, you can use a go array pointer value, such as *[30]uint32 and assign the pointer to the C data via unsafe.Pointer. If it's variable length, you can construct a []uint32 slice header using unsafe and reflect.
or just use a ridiculously large array length, for example, 1<<32, and then slice it. 

Sonia Hamilton

unread,
Jan 25, 2013, 8:37:38 AM1/25/13
to golan...@googlegroups.com
* Andy Balholm <andyb...@gmail.com> [2013-01-24 20:33:42 -0800]:
* Kevin Gillette <extempor...@gmail.com> [2013-01-24 19:27:24 -0800]:

> If the length of the C array is invariant, you can use a go array pointer
> value, such as *[30]uint32 and assign the pointer to the C data via
> unsafe.Pointer. If it's variable length, you can construct a []uint32 slice
> header using unsafe and reflect.

* minux <minu...@gmail.com> [2013-01-25 18:21:54 +0800]:

> or just use a ridiculously large array length, for example, 1<<32, and then
> slice it.

Thanks guys. I couldn't get slice conversion working (I was following
[1]). In the end I used GoBytes() and binary.Read(); any improvements on
this solution?

> // OidToStr converts an oid from C array of guint32's to a Go string
> func OidToStr(oid *_Ctype_guint32, oid_len _Ctype_gsize) (result string) {
> size := int(unsafe.Sizeof(oid))
> length := int(oid_len)
> gbytes := C.GoBytes(unsafe.Pointer(oid), (_Ctype_int)(size*length))
>
> buf := bytes.NewBuffer(gbytes)
> for i := 0; i < length; i++ {
> var out uint32
> if err := binary.Read(buf, binary.LittleEndian, &out); err == nil {
> result = result + fmt.Sprintf(".%d", out)
> } else {
> return "<error converting oid>"
> }
> }
> return result[1:]
> }

[1] https://code.google.com/p/go-wiki/wiki/cgo, "Turning C arrays into
Go slices"
Reply all
Reply to author
Forward
0 new messages