如何将C函数中的字符串读入Go?

时间:2016-10-24 07:32:38

标签: c go cgo

我试图通过cgo从Go调用C函数来读取错误消息。该函数生成一个长度小于256字节的消息。

C中的工作示例:

char message[ERROR_SIZE]; //256
last_error( message, sizeof(message) );         
printf( "message: %s\n", message );

我尝试Go(不工作):

var ptr *C.char
C.last_error(ptr, ERROR_SIZE)
var message = C.GoString(ptr)
fmt.Printf("message: %s\n", message)

运行go代码时,消息为空。 go版本是否需要预先为消息分配空间?怎么做?

在LP发表评论后更新以传递数组。这有效,但似乎有点尴尬:

var buf [ERROR_SIZE]byte
var ptr = (*C.char)(unsafe.Pointer(&buf[0]))
C.last_error(ptr, len(buf))
var message = C.GoString(ptr)
fmt.Printf("message: %s\n", message)

有更简单的方法吗?

1 个答案:

答案 0 :(得分:2)

在你的第一个例子中,你传递了一个nil指针,因此C.last_error没有分配内存来写输出(幸运的是,它似乎什么都不做)。

你需要以某种方式分配内存,而在Go中最直接的方法是使用切片,而不是创建一个静态大小的数组。

buf := make([]byte, ERROR_SIZE)
C.last_error((*C.char)(unsafe.Pointer(&buf[0])), len(buf))

// While C.GoString will find the terminating null if it's there, 
// there's no reason to copy the string in C, and allocate another slice.
if i := bytes.IndexByte(buf, 0); i >= 0 {
    buf = buf[:i]
}

fmt.Printf("message: %s\n", buf)