Right way to convert c char to golang bytes

2,185 views
Skip to first unread message

Balaji Rajendran

unread,
Jun 6, 2020, 2:57:41 AM6/6/20
to golang-nuts
I want to convert *C.uchar to bytes slice.

I've tried C.GoBytes. But, C.GoBytes is not giving the exact result. Because, it is truncating at zero.

for example.

If I have *C.uchar like this, [1,3,5,0,2,4,5]. I expect my go bytes like this [1,3,5,0,2,4,5]

But, I get [1,3,5,0,0,0] If I use C.Gobytes.

I'm able to get the correct results, If I do a casting like this
func charToBytes(src *C.uchar, sz int) []byte {
dest := make([]byte, sz)
copy(dest, (*(*[1024]byte)(unsafe.Pointer(src)))[:sz:sz])
return dest
}

Is this a safe code? And also how to increase the size of slice dynamically. Right now it is capped at 1024

Tamás Gulácsi

unread,
Jun 6, 2020, 3:35:27 AM6/6/20
to golang-nuts
Use 1<<31 instead of 1024.
And ifthe C side won't modify/free the *uchar, then you don't need the copy.

peterGo

unread,
Jun 6, 2020, 10:44:51 AM6/6/20
to golang-nuts
Tamás,

You have an off-by-one error. For 32-bit ints, maxInt is 1<<31 - 1, not 1<<31.

For GOARCH=386,

constant 2147483648 overflows int
array bound is too large

Peter

Tamás Gulácsi

unread,
Jun 6, 2020, 11:32:13 AM6/6/20
to golang-nuts
:-)

Thanks!

Jake Montgomery

unread,
Jun 6, 2020, 11:52:31 AM6/6/20
to golang-nuts
Can you post some code that reproduces the C.GoBytes() behavior you see? According to the documentation it should work as you expect.
This "simulation" works (but can not be run in the playground because of cgo usage): https://play.golang.org/p/gec7VNy4-UW

Bryan C. Mills

unread,
Jun 8, 2020, 4:37:02 PM6/8/20
to golang-nuts
Note that in general C strings are not restricted to 2³¹ bytes on 64-bit systems.
(Larger strings are unusual, but fairly trivial to construct.)
So I would recommend avoiding hard-coded array types of any size.

You say that C.GoBytes truncates at zero. However, that does not reproduce for me.
Are you sure that you are passing in the correct value for `sz`?


example.com$ cat main.go
package main

import (
        "fmt"
        "unsafe"
)

/*
#include <stddef.h>
#include <string.h>

char* message() {
        return "Hello,\0 Go";
}
*/
import "C"

func charToBytes(src *C.char, sz int) []byte {
        return C.GoBytes(unsafe.Pointer(src), C.int(sz))
}

func main() {
        b := charToBytes(C.message(), 10)
        fmt.Printf("%s\n", b)
}

example.com$ go run main.go
Hello, Go

Reply all
Reply to author
Forward
0 new messages