Turn string into const char *

1,818 views
Skip to first unread message

Florian Weimer

unread,
Feb 27, 2011, 6:54:20 AM2/27/11
to golan...@googlegroups.com
I know this seems to come up periodically, but I still think it's
pretty strange that I cannot pass a Go string to a C function which
expects const char */size_t pair (pointer to the first character and
string length). Wouldn't it make sense to enable this use?

There might be issues if Go ever acquires a compacting garbage
collector, of course, but pointers into []byte share them, and adding
strings into the mix doesn't seem like much of an additional burden to
me.

William Waites

unread,
Feb 27, 2011, 7:29:53 AM2/27/11
to Florian Weimer, golan...@googlegroups.com
* [2011-02-27 12:54:20 +0100] Florian Weimer <f...@deneb.enyo.de> �crit:

] I know this seems to come up periodically, but I still think it's


] pretty strange that I cannot pass a Go string to a C function which
] expects const char */size_t pair (pointer to the first character and
] string length). Wouldn't it make sense to enable this use?

You can do it with something like this,

sbytes := []byte(mystring)
ccp := (*C.char)(unsafe.Pointer(&sbytes[0]))

but not quite directly and the bookkeeping there is
more than a little ungolike...

Cheers,
-w
--
William Waites <mailto:w...@styx.org>
http://river.styx.org/ww/ <sip:w...@styx.org>
F4B3 39BF E775 CF42 0BAB 3DF0 BE40 A6DF B06F FD45

Florian Weimer

unread,
Feb 27, 2011, 7:35:54 AM2/27/11
to William Waites, golan...@googlegroups.com
* William Waites:

> * [2011-02-27 12:54:20 +0100] Florian Weimer <f...@deneb.enyo.de> écrit:
>
> ] I know this seems to come up periodically, but I still think it's
> ] pretty strange that I cannot pass a Go string to a C function which
> ] expects const char */size_t pair (pointer to the first character and
> ] string length). Wouldn't it make sense to enable this use?
>
> You can do it with something like this,
>
> sbytes := []byte(mystring)
> ccp := (*C.char)(unsafe.Pointer(&sbytes[0]))
>
> but not quite directly and the bookkeeping there is
> more than a little ungolike...

I believe the first line makes a copy of the string. This is
particular wasteful if you're itering through slices of a larger
string.

Right now, I'm using []byte instead of string, but I would like to
offer an efficient interface with strings, too.

Dmitry Chestnykh

unread,
Feb 27, 2011, 10:16:40 AM2/27/11
to golan...@googlegroups.com
On Sunday, February 27, 2011 12:54:20 PM UTC+1, Florian Weimer wrote:
I know this seems to come up periodically, but I still think it's
pretty strange that I cannot pass a Go string to a C function which
expects const char */size_t pair (pointer to the first character and
string length).  Wouldn't it make sense to enable this use?

C.CString(s) ?

-Dmitry

William Waites

unread,
Feb 27, 2011, 10:55:46 AM2/27/11
to golan...@googlegroups.com
* [2011-02-27 07:16:40 -0800] Dmitry Chestnykh <dch...@gmail.com> �crit:

> C.CString(s) ?

Which will definitely copy the string...

Using a pointer to the beginning string directly would only
be possible for calls that take a size/length argument since
they are not null terminated in go. So to do this automatically,
how would cgo be able to tell the semantics of the C
function?

Imagine

int count_ascii_digits(const char *s, size_t len)
C.count_ascii_digits("123abc")

vs.

int write_height_to_paper_tape(const char *name, size_t height)
C.write_height_to_paper_tape("bob")

You might reasonably expect to be able to do the first but
the second makes no sense. And they would look the same to the
compiler.

Maybe a convenience function like

func C.StrToConst(s string) (ccp *C.char, len C.size_t)

would be useful.

Florian Weimer

unread,
Feb 27, 2011, 11:05:05 AM2/27/11
to William Waites, golan...@googlegroups.com
* William Waites:

> Using a pointer to the beginning string directly would only
> be possible for calls that take a size/length argument since
> they are not null terminated in go. So to do this automatically,
> how would cgo be able to tell the semantics of the C
> function?

I'm not asking for a magic conversion.

> Maybe a convenience function like
>
> func C.StrToConst(s string) (ccp *C.char, len C.size_t)
>
> would be useful.

Yes, something to do this explicitly would be sufficient. Right now,
there doesn't seem to do be a way at all.

John Asmuth

unread,
Feb 27, 2011, 11:23:20 AM2/27/11
to golang-nuts

> > Maybe a convenience function like
>
> >       func C.StrToConst(s string) (ccp *C.char, len C.size_t)
>
> > would be useful.
>
> Yes, something to do this explicitly would be sufficient.  Right now,
> there doesn't seem to do be a way at all.

The problem with this is that go strings are not null terminated. If
you take the exact memory of a go string and try to use it as a C
string, things are going to go very wrong if you, for instance, do IO
with it or do anything from strings.h.

I imagine this might work, though, if you don't care about the null
terminator.

*((**byte)(unsafe.Pointer(&theString)))

Now you've got a *byte, which can be treated like a char*.

- John

Florian Weimer

unread,
Feb 27, 2011, 11:36:05 AM2/27/11
to John Asmuth, golang-nuts
* John Asmuth:

>> > Maybe a convenience function like
>>
>> >       func C.StrToConst(s string) (ccp *C.char, len C.size_t)
>>
>> > would be useful.
>>
>> Yes, something to do this explicitly would be sufficient.  Right now,
>> there doesn't seem to do be a way at all.
>
> The problem with this is that go strings are not null terminated. If
> you take the exact memory of a go string and try to use it as a C
> string, things are going to go very wrong if you, for instance, do IO
> with it or do anything from strings.h.

As I said, I'm working with C APIs which expect an explicit length.
These are pretty commonplace: write(), pcre_exec() (but not
pcre_compile()), sqlite3_prepare(), DBTs, and pretty much everything
in C++ land.

Sure, there are other interfaces which are incompatible, but I don't
think their mere existence should preclude simple and efficient use of
the C interfaces which do not suffer from this problem.

Florian Weimer

unread,
Feb 27, 2011, 11:44:45 AM2/27/11
to John Asmuth, golang-nuts
* John Asmuth:

> I imagine this might work, though, if you don't care about the null
> terminator.
>
> *((**byte)(unsafe.Pointer(&theString)))
>
> Now you've got a *byte, which can be treated like a char*.

Ah, I missed the "**" on the first reading. This is extremely ugly,
but it does work (currently---I'm aware that it depends on the
internal representation of strings). Thanks.

John Asmuth

unread,
Feb 27, 2011, 2:46:44 PM2/27/11
to golang-nuts
On Feb 27, 11:44 am, Florian Weimer <f...@deneb.enyo.de> wrote:
> I'm aware that it depends on the internal representation of strings

Sure, I just like to put disclaimers when I post something that could
cause weird errors for an less-than-careful programmer. You're not the
only one who will read it ;)

- John

Eleanor McHugh

unread,
Feb 27, 2011, 8:39:40 PM2/27/11
to golang-nuts
The last couple of days I've been working on RAW, a library for manipulating arbitrary types as byte slices. The impetus is a CGO wrapper that I'm designing for Apple's Objective-C runtime so I can write Cocoa apps in Go, but I'm also thinking of rolling in the various odd unsafe and reflection tricks I've discovered whilst researching GoLightly.

RAW has a function Buffer(interface{}) which constructs valid byte slice headers with reflection and an interface Buffered for providing custom overrides on user defined types. Aside from generating a base address and length for passing to C routines it also allows the various I/O interfaces in the standard library to operate on chunks of memory. I don't have a use for this particular capability but I like the potential symmetry it offers.

I'll probably also add in support for some C stdlib calls such as malloc() for completeness though they're of limited usefulness in Go's runtime environment.

For those interested in the naming, RAW stands for either "Random Access Woe" or "Read-it And Weep", and the library can be downloaded from http://github.com/feyeleanor/raw.


Ellie

Eleanor McHugh
Games With Brains
http://feyeleanor.tel/
----
raise ArgumentError unless @reality.responds_to? :reason

Reply all
Reply to author
Forward
0 new messages