2016-10-24 39 views
1

我想從cgo中調用C函數來讀取錯誤消息。該函數產生一個長度小於256字節的未知長度的消息。用C如何從C函數中將字符串讀入Go?

工作例如:

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

我在圍棋(不工作)的嘗試:

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

不是[tag:go]專家,但是[tag:c]函數需要一個數組。從[tag:go]方面你傳遞一個簡單的指針。 – LPs

+1

感謝您的評論@LPs,聲明一個數組並傳遞指向第一個元素的指針(該函數實際上接受一個char *)。該消息被打印。 – Mark

+0

'C.GoString'根據需要分配空間,只要你有一個以空字符結尾的字符串,它就應該在這個實例中工作。如果字符串不是以null結尾,或者可能包含空字符,則將其視爲字節,並使用'C.GoBytes'。 – JimB

回答

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) 
+0

輝煌,謝謝@JimB。欣賞提示以避免複製。 – Mark

相關問題