[cgo] C array to Go array without explicit copying

1,430 views
Skip to first unread message

salviati

unread,
Jun 6, 2011, 9:00:00 PM6/6/11
to golang-nuts
I have a C function that returns me a fairly huge char array (I know
the size of the array, of course). I'd like to wrap this function
using cgo, and avoid possible overheads (cpu, memory); is there a way
to do this? Any work-arounds?

Gustavo Niemeyer

unread,
Jun 6, 2011, 9:20:06 PM6/6/11
to salviati, golang-nuts
Hey there,

> I have a C function that returns me a fairly huge char array (I know

How huge, just to have an idea?

> the size of the array, of course). I'd like to wrap this function
> using cgo, and avoid possible overheads (cpu, memory); is there a way
> to do this? Any work-arounds?

I'd recommend starting with something trivial: just copy the array
once into a []byte using a normal conversion, and then use that to
pass around in Go. If you figure the penalty of copying between C and
Go is really creating issues, you can play with the unsafe package in
a few different ways (some less safe than others).

Can you provide the array (memory) for the C function to work with, or
does the library allocate and provide it to you?

--
Gustavo Niemeyer
http://niemeyer.net
http://niemeyer.net/blog
http://niemeyer.net/twitter

salviati

unread,
Jun 6, 2011, 9:28:51 PM6/6/11
to golang-nuts
*Might* be huge enough (even at the order of gigabytes) that I'm
trying to avoid copying. Explicit copying is almost certain to cause
problems.
Nope, the C code allocates the buffer for me. It was designed this
way, because library can't predict the output length of the buffer
beforehand.

I was wondering whether if I can construct a Go array at C size, using
a struct like {data, length, capacity}, or something similar (which
would be the best case solution for me).

Gustavo Niemeyer

unread,
Jun 6, 2011, 9:34:59 PM6/6/11
to salviati, golang-nuts
> I was wondering whether if I can construct a Go array at C size, using
> a struct like {data, length, capacity}, or something similar (which
> would be the best case solution for me).

Yes, you can do that using unsafe.Pointer and a type like
reflect.SliceHeader. Be aware that you'll have to manage the memory
of the array entirely by hand, and it will explode in unfriendly ways
if you don't deal with it properly. This is also unsafe, and not
guaranteed to work in the future.

Davies Liu

unread,
Jun 6, 2011, 9:37:00 PM6/6/11
to salviati, golang-nuts
            buf = (*[1 << 30]byte)(unsafe.Pointer(cbuf))[:clen]
            (*reflect.SliceHeader)(unsafe.Pointer(&buf)).Cap = clen
--
 - Davies

salviati

unread,
Jun 6, 2011, 9:52:43 PM6/6/11
to golang-nuts
Thanks, Davies!

Gustavo, I guess I can make a new typedef for the byte array, and
assign a finalizer that calls C.free(), so that GC will handle the
object automatically.

Gustavo Niemeyer

unread,
Jun 6, 2011, 10:09:38 PM6/6/11
to salviati, golang-nuts
> Gustavo, I guess I can make a new typedef for the byte array, and
> assign a finalizer that calls C.free(), so that GC will handle the
> object automatically.

That won't work. The GC won't manage that memory region, so there are
no finalizers there either.

xophos

unread,
Jun 7, 2011, 4:26:41 AM6/7/11
to golang-nuts
Why not keep the c array as such and write accessor functions in cgo?
Seems a lot simpler to me.
Reply all
Reply to author
Forward
0 new messages