目前我正在使用Cgo从Go调用C函数。我正在尝试在Go中重新创建'Read a Photo'示例。
然而,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 :(得分:7)
这似乎对我有用:
package main
/*
void foo(int *len) { *len = 1234; }
*/
import "C"
func main() {
var x C.int
C.foo(&x)
println(x)
}
答案 1 :(得分:4)
这里的问题是你有两种不同的类型。你有一个int
由你的Go编译器定义,C.int
由你的C编译器定义。根据编译器和体系结构,这些可能大小相同。但是,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
中。
Bonus Anwser:int* len
确实与int *len
答案 2 :(得分:2)
您需要unsafe.Pointer
演员。
C.ccv_write(image.image, dst, (*C.int)(unsafe.Pointer(&x)), C.CCV_IO_PNG_FILE, 0)