Converting a C char[] to []byte of string with cgo

843 views
Skip to first unread message

Dean Schulze

unread,
Apr 30, 2020, 2:17:37 PM4/30/20
to golang-nuts
I must be missing something pretty simple, but I have a C struct like this:

typedef struct line
{
    char hostname[HOSTNAME_MAX];
    char ip[IP_MAX];
    ...
}

When I try to do the simple thing

C.GoString(p.hostname)

I get an error like

cannot use p.hostname (type [25]_Ctype_char) as type *_Ctype_char in argument to _Cfunc_GoString

I've seen some examples but they all rely on *C.char and I haven't found any way to get a [25]_Ctype_char to a pointer representation.

What do I need to do to convert a char[] to []byte of string in Go?

Dean Schulze

unread,
Apr 30, 2020, 2:42:43 PM4/30/20
to golang-nuts
I've also tried this

var src [24]C.char = p.mach_ip

and this

var src *[24]C.char = &p.mach_ip

and both give panics.

Jan Mercl

unread,
Apr 30, 2020, 3:46:34 PM4/30/20
to Dean Schulze, golang-nuts
On Thu, Apr 30, 2020 at 8:17 PM Dean Schulze <dean.w....@gmail.com> wrote:
>
> I must be missing something pretty simple, but I have a C struct like this:
>
> typedef struct line
> {
> char hostname[HOSTNAME_MAX];
> char ip[IP_MAX];
> ...
> }
>
> When I try to do the simple thing
>
> C.GoString(p.hostname)

An array of a fixed size within a C struct is a value (the same as in
Go), but C.GoString expects a pointer to a C.char. Try
`C.GoString(&p.hostname)`.

Not tested. Note that if hostname is not properly zero terminated,
your code will crash or misbehave.

(Automatic array decay applies to C code, but not in Go.)

Dean Schulze

unread,
Apr 30, 2020, 4:05:40 PM4/30/20
to golang-nuts
That gives this error (which I've gotten with just about everything I try):

cannot use &p.mach_name (type *[25]_Ctype_char) as type *_Ctype_char in argument to _Cfunc_GoString

It seems to be the fixed length of the char[] that gives cgo a problem.


On Thursday, April 30, 2020 at 1:46:34 PM UTC-6, Jan Mercl wrote:

Bruno Albuquerque

unread,
Apr 30, 2020, 4:09:54 PM4/30/20
to Dean Schulze, golang-nuts
Not pretty but if you are sure the array is zero-terminated, you can simply cast it to the correct type:

C.GoString((C.char*)(&p.hostname))

(untested)


--
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.
To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/72d6cdaa-a6ca-4a60-b60a-a3a42de5d8d6%40googlegroups.com.

mi...@pekim.co.uk

unread,
Apr 30, 2020, 4:14:22 PM4/30/20
to golang-nuts

C.GoString((*C.char)(&p.hostname))


Jan Mercl

unread,
Apr 30, 2020, 4:19:16 PM4/30/20
to Dean Schulze, golang-nuts
On Thu, Apr 30, 2020 at 10:06 PM Dean Schulze <dean.w....@gmail.com> wrote:
>
> That gives this error (which I've gotten with just about everything I try):
>
> cannot use &p.mach_name (type *[25]_Ctype_char) as type *_Ctype_char in argument to _Cfunc_GoString

Oh yeah, should have been probably `C.GoString(&p.hostname[0])`.
Forgot Go has stronger type discipline than C. (Not tried still.)

Dean Schulze

unread,
Apr 30, 2020, 4:21:39 PM4/30/20
to Bruno Albuquerque, golang-nuts
  This expression

    C.GoString(C.char*(&p.mach_name))

gives this error:

    type _Ctype_char is not an expression

Bruno Albuquerque

unread,
Apr 30, 2020, 4:24:27 PM4/30/20
to Dean Schulze, golang-nuts
C.GoString((*C.char)(&p.mach_name))

Dean Schulze

unread,
Apr 30, 2020, 4:24:58 PM4/30/20
to Jan Mercl, golang-nuts
That compiles but it still panics:
 
test: bad machine line11=(null), return
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x4949f2]

goroutine 1 [running]:
main.(*LineStruct).MachineName(...)
        /home/dean/src/test.slurm.integration/test.conf.file.parser/golang/test.conf.file.parser.test.go:27
main.main()
        /home/dean/src/test.slurm.integration/test.conf.file.parser/golang/test.conf.file.parser.test.go:61 +0x52

peterGo

unread,
Apr 30, 2020, 4:28:41 PM4/30/20
to golang-nuts
Dean,

Command cgo
https://golang.org/cmd/cgo/#hdr-Go_references_to_C

In C, a function argument written as a fixed size array actually requires a pointer to the first element of the array. C compilers are aware of this calling convention and adjust the call accordingly, but Go cannot. In Go, you must pass the pointer to the first element explicitly: C.f(&C.x[0]).

Peter

Dean Schulze

unread,
Apr 30, 2020, 6:10:51 PM4/30/20
to Jan Mercl, golang-nuts
That works.  The problem I had earlier with a panic was caused by my C library which was returning null as an error condition.  Once the C code was fixed it worked as you said.

Thanks.
Reply all
Reply to author
Forward
0 new messages