Cgo: How to access arbitrary element of C float array

3,890 views
Skip to first unread message

John Barham

unread,
Mar 6, 2013, 6:28:12 AM3/6/13
to golang-nuts
I'm calling a C function that returns a float** value which I want to
copy into a Go slice, but am getting an indexing error.

The code looks something like:

var cpix **C.float = C.readPixels(infile)
defer C.free(unsafe.Pointer(cpix))
pix := make([]float32, n)
for i := 0; i < n; i++ {
pix[i] = cpix[i]
}

but the error I'm getting is: invalid operation: cpix[i] (index of
type **_Ctype_float)

So seems like I can't do indexing into C arrays from Go.

Thanks for any help.

John

minux

unread,
Mar 6, 2013, 6:37:43 AM3/6/13
to John Barham, golang-nuts
Go doesn't have pointer arithmetic and so it can't do access like this pointer[index], because
that means *(pointer + index) [another reason is that a pointer doesn't contain a limit for index,
so allowing that will effectively make unconstrained memory access possible].

you have a few alternatives here (take C's "int *p" as an example):
1. the hard one: cast the pointer into unsafe.Pointer and then uintptr, do the pointer arithmetic
(remember you need uintptr(unsafe.Pointer(p)) + unsafe.Sizeof(C.int(0)) * i to take size of int
into account) and then cast it back to a pointer through unsafe.Pointer.

2. make the pointer a pointer to a large Go array.
p2 := (*[1<<30]C.int)unsafe.Pointer(p)
then you can use p2[index] to access p[index].

special notice: Go's int type is not necessarily the same as C's, so be aware.

Rémy Oudompheng

unread,
Mar 6, 2013, 6:51:15 AM3/6/13
to minux, John Barham, golang-nuts
It is also possible to make() a Go slice and use C.memcpy to fill it
(with the same unsafeties as the other methods).

Rémy.

2013/3/6, minux <minu...@gmail.com>:
> --
> You received this message because you are subscribed to the Google Groups
> "golang-nuts" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to golang-nuts...@googlegroups.com.
> For more options, visit https://groups.google.com/groups/opt_out.
>
>
>

John Barham

unread,
Mar 6, 2013, 5:12:34 PM3/6/13
to minux, golang-nuts
On Wed, Mar 6, 2013 at 10:37 PM, minux <minu...@gmail.com> wrote:
> 2. make the pointer a pointer to a large Go array.
> p2 := (*[1<<30]C.int)unsafe.Pointer(p)
> then you can use p2[index] to access p[index].

This is working for me, with addition of extra parens around
unsafe.Pointer: p2 := (*[1<<30]C.int)(unsafe.Pointer(p)).

Many thanks!

John

Herbert Fischer

unread,
May 2, 2013, 9:04:31 PM5/2/13
to John Barham, minux, golang-nuts
I'm getting into the same issue but I would like to understand better what this line means:

p2 := (*[1<<30]C.int)(unsafe.Pointer(p)).

specially: (*[1<<30]C.int)  - why 1<<30 ??


Herbert Fischer

unread,
May 2, 2013, 9:14:50 PM5/2/13
to John Barham, minux, golang-nuts
Nevermind. Already got it.

Camilo Aguilar

unread,
Nov 5, 2013, 11:30:11 AM11/5/13
to golan...@googlegroups.com, John Barham, minux
I still don't get  1<<30, what does it do?

chris dollin

unread,
Nov 5, 2013, 11:45:54 AM11/5/13
to Camilo Aguilar, golang-nuts, John Barham, minux
On 5 November 2013 16:30, Camilo Aguilar <camilo....@gmail.com> wrote:
I still don't get  1<<30, what does it do?

<< is bit shift left; each shift multiplies by 2, so 1 << 30 is 2 to-the-power-of 30, a computational billion.

(And the (*[1<<30]C.int) is a type which is "pointer to a billion-C-int array".)



--
Chris "allusive" Dollin

minux

unread,
Nov 5, 2013, 12:00:33 PM11/5/13
to Camilo Aguilar, John Barham, golang-nuts


On Nov 5, 2013 11:30 AM, "Camilo Aguilar" <camilo....@gmail.com> wrote:
> I still don't get  1<<30, what does it do?

just an arbitrary big number (hopefully big enough for your slice length/capacity) for the length of the array, so that you can slice it with the length you want.

Camilo Aguilar

unread,
Nov 5, 2013, 2:17:51 PM11/5/13
to golan...@googlegroups.com, Camilo Aguilar, John Barham
how would it be if I know the length of the C array? 

minux

unread,
Nov 5, 2013, 2:27:38 PM11/5/13
to Camilo Aguilar, John Barham, golang-nuts


On Nov 5, 2013 2:17 PM, "Camilo Aguilar" <camilo....@gmail.com> wrote:
>
> how would it be if I know the length of the C array? 

it you know the length statically (that you can write down the number in source code as a constant), you can use that constant as the array length.

but if it is stored in a variable, you will have to use the 1<<30 trick, because arrays in Go must have statically determined bounds.

Camilo Aguilar

unread,
Nov 5, 2013, 2:34:55 PM11/5/13
to golan...@googlegroups.com, Camilo Aguilar, John Barham
I see... I believe I understand better now, thank for for your quick response!. 
Reply all
Reply to author
Forward
0 new messages