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.
] 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
> * [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.
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) ?
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.
> 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.
>> > 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.
> 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.
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