2012-11-16 35 views
0

目前我使用Cgo從Go調用C函數。我試圖在Go中重新創建'Read a Photo'示例。CGO; C函數有int指針參數,如何傳遞正確的類型?

然而,一個關於C函數的參數需要int* len參數(獎勵問題;是否與int *len?相同)。當我讀到這個時,這是一個指向整數的指針。有問題的函數是libccv庫的ccv_write。它的完整的簽名是:

int ccv_write(ccv_dense_matrix_t* mat, char* out, int* len, int type, void* conf)

相關的代碼片段如下:

type Image struct { 
    image *C.ccv_dense_matrix_t 
} 

func main() { 
    image := new(Image) 

    /* ... snip ... */ 

    dst := C.CString("black_and_white_painting.jpg") 
    defer C.free(unsafe.Pointer(dst)) 
    x := 0 // <- perhaps var x int ? 
    C.ccv_write(image.image, dst, (*C.int)(&x), C.CCV_IO_PNG_FILE, 0) 
} 

上面的例子生成以下編譯時錯誤:cannot convert &x (type *int) to type *_Ctype_int

如何通過任何想法正確的論點?

+0

是,在空白C是很少顯著,'INT * LEN;'和'INT len個*;'是等價的。有理由(在我看來)更喜歡前者,因爲後者看起來像是有前途的東西(即'int * a,b;'是什麼意思?)。 – unwind

回答

4

這裏的問題是你有兩種不同的類型。您的Go編譯器定義了int,您的C編譯器定義了C.int。根據編譯器和體系結構的不同,這些大小可能相同。然而,int很可能是64位大小,而C.int會是32位。

爲了讓編譯器強制執行類型安全性,它需要您進行顯式轉換或在初始化時定義類型。

在你的例子中,你這樣做:x := 0。這與x := int(0)相同。隱含int。相反,你可以做x := C.int(0)

但是,我認爲「更乾淨」的方法是做什麼jnml推薦:var x C.int。這件事情完全一樣,但看起來更好。


之後,你很可能要轉換的是C.int回到一個int。轉換很容易。

y := int(x) 

這將x轉換爲int,然後複製值到新初始化的變量y


獎金Anwser:int* len確實是一樣的int *len

5

這似乎爲我工作:

package main 

/* 

void foo(int *len) { *len = 1234; } 

*/ 
import "C" 

func main() { 
     var x C.int 
     C.foo(&x) 
     println(x) 
} 
1

您將需要一個unsafe.Pointer投。

C.ccv_write(image.image, dst, (*C.int)(unsafe.Pointer(&x)), C.CCV_IO_PNG_FILE, 0) 
+1

這是爲什麼這是必要的? – harm

+0

這是允許您嘗試實現的轉換的唯一方法。從[文檔](http://golang.org/pkg/unsafe/#Pointer):'unsafe.Pointer'允許程序打敗類型系統並讀寫任意內存。應該非常小心地使用它。 – jimt

+1

另一種方法是將'x'定義爲'var x C.int'。然後你可以把它作爲'&x'來傳遞。如果你的'x'來自你的包之外,這將不起作用。 – jimt