我试图通过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)
有更简单的方法吗?
答案 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)