Cgo and C String Buffers

1,488 views
Skip to first unread message

Rob Thornton

unread,
Sep 24, 2011, 9:30:43 PM9/24/11
to golang-nuts
As an exercise for myself to learn Go and Cgo, I am working on my own
implementation of ncurses (I realize there is already a package for
curses). My plan is to implement the entire ncurses library. I am
using a working name of goncurses. I am stuck on how to create a char
buffer and convert the result to a Go string. Consider the following:

func Getstr() string {
var cstr [256]C.char
if C.getstr((*C.char)(unsafe.Pointer(&cstr[0]))) == C.ERR {
return "", os.NewError("Failed to retrieve string from input
stream")
}
return C.GoString(cstr), nil // error, GoString expects a *C.char
}

I need to allocate enough space for the buffer to work, otherwise I
get a runtime error. I'd use make to create the array but make doesn't
appear to work with C types. Understandable. I'd rather not have to
rely on a set buffer size if I can help it, either, but I don't see
any way around that. Is there a way to convert the buffer back into a
C pointer? I suppose I could use sprintf but I was hoping to avoid
using additional C libraries.

Any thoughts?

Matt Kane's Brain

unread,
Sep 24, 2011, 9:41:55 PM9/24/11
to Rob Thornton, golang-nuts
On Sat, Sep 24, 2011 at 21:30, Rob Thornton <ro...@telus.net> wrote:
> I need to allocate enough space for the buffer to work, otherwise I
> get a runtime error. I'd use make to create the array but make doesn't
> appear to work with C types.

Huh? What happens when you try to make a []C.char?

> Understandable. I'd rather not have to
> rely on a set buffer size if I can help it, either, but I don't see
> any way around that. Is there a way to convert the buffer back into a
> C pointer?

&c[0] should be fine. I think it's even the correct type.

--
matt kane's brain
http://hydrogenproject.com

Rob Thornton

unread,
Sep 25, 2011, 10:52:05 AM9/25/11
to golang-nuts


On Sep 24, 6:41 pm, "Matt Kane's Brain" <mkb-
pr...@hydrogenproject.com> wrote:
> On Sat, Sep 24, 2011 at 21:30, Rob Thornton <ro...@telus.net> wrote:
> > I need to allocate enough space for the buffer to work, otherwise I
> > get a runtime error. I'd use make to create the array but make doesn't
> > appear to work with C types.
>
> Huh? What happens when you try to make a []C.char?

When I try and use []C.char in the first instance I get the following
error:

panic: runtime error: index out of range

Presumably because I've not actually allocated any space for the
array.

> > Understandable. I'd rather not have to
> > rely on a set buffer size if I can help it, either, but I don't see
> > any way around that. Is there a way to convert the buffer back into a
> > C pointer?
>
> &c[0] should be fine. I think it's even the correct type.
>
> --
> matt kane's brainhttp://hydrogenproject.com

Yes, this works exactly as I need! Thank you! I think I'll just have
to suffer with a static array size.

Matt Kane's Brain

unread,
Sep 25, 2011, 10:54:40 AM9/25/11
to Rob Thornton, golang-nuts
On Sun, Sep 25, 2011 at 10:52, Rob Thornton <ro...@telus.net> wrote:
> When I try and use []C.char in the first instance I get the following
> error:
>
> panic: runtime error: index out of range
>
> Presumably because I've not actually allocated any space for the
> array.

Yeah, you need to do:
cstr := make([]C.char, wotsize)

Gustavo Niemeyer

unread,
Sep 25, 2011, 1:50:11 PM9/25/11
to Rob Thornton, golang-nuts
> I need to allocate enough space for the buffer to work, otherwise I
> get a runtime error

Are you sure? You're not providing the buffer length, so it's more
likely that there's a known buffer size you have to provide, or
worse.. it will just crash. I'd look further before using this API.

Either way, to your question..

> I'd use make to create the array but make doesn't
> appear to work with C types. Understandable. I'd rather not have to
> rely on a set buffer size if I can help it, either, but I don't see

If you're in the Go side, just use Go types..

b := make([]byte, n)
... unsafe.Pointer(&b[0]) ...
return string(b)

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

-- I never filed a patent.

Kevin Ballard

unread,
Sep 25, 2011, 6:10:18 PM9/25/11
to Gustavo Niemeyer, Rob Thornton, golang-nuts
On Sun, Sep 25, 2011 at 10:50 AM, Gustavo Niemeyer <gus...@niemeyer.net> wrote:
> I need to allocate enough space for the buffer to work, otherwise I
> get a runtime error

Are you sure? You're not providing the buffer length, so it's more
likely that there's a known buffer size you have to provide, or
worse.. it will just crash. I'd look further before using this API.

getstr() is inherently unsafe because it doesn't provide a length. You really should be using getnstr() instead, which does take one.

Rob Thornton

unread,
Sep 25, 2011, 9:57:56 PM9/25/11
to golang-nuts
@Gustavo: Thank you for the make() tip! Exactly what I was looking
for.

@Kevin: Funnily enough, I already beat you to the punch. I have
already changed to using getnstr(). Thanks!

On Sep 25, 3:10 pm, Kevin Ballard <kball...@gmail.com> wrote:
> On Sun, Sep 25, 2011 at 10:50 AM, Gustavo Niemeyer <gust...@niemeyer.net>wrote:
>
> > > I need to allocate enough space for the buffer to work, otherwise I
> > > get a runtime error
>
> > Are you sure? You're not providing the buffer length, so it's more
> > likely that there's a known buffer size you have to provide, or
> > worse.. it will just crash. I'd look further before using this API.
>
> getstr() is inherently unsafe because it doesn't provide a length. You
> really should be using getnstr() instead, which does take one.
>
> -Kevin
>
> --
> Kevin Ballardhttp://kevin.sb.org
> kball...@gmail.com
Reply all
Reply to author
Forward
0 new messages