英文:
CGO; C function has int pointer argument, how to pass correct type?
问题
目前我正在使用Cgo从Go中调用C函数。我正在尝试在Go中重新创建“读取照片”示例。
然而,其中一个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)
/* ... 省略 ... */
dst := C.CString("black_and_white_painting.jpg")
defer C.free(unsafe.Pointer(dst))
x := 0 // <- 或许应该是 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
对于如何传递正确的参数,有什么想法吗?
英文:
Currently I'm using Cgo to call C functions from Go. I'm trying to recreate the 'Read a Photo' example in Go.
One on the C functions, however, expects a int* len
argument (bonus question; is that the same as int *len
?). As I read this, this is a pointer to an integer. The function in question is ccv_write
of the libccv library. It's full signature is:
int ccv_write(ccv_dense_matrix_t* mat, char* out, int* len, int type, void* conf)
The relevant code snippet is as follows:
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)
}
The above example generates the following compile time error: cannot convert &x (type *int) to type *_Ctype_int
Any thoughts on how to pass the correct argument?
答案1
得分: 9
这对我来说似乎有效:
package main
/*
void foo(int *len) { *len = 1234; }
*/
import "C"
func main() {
var x C.int
C.foo(&x)
println(x)
}
英文:
This seems to work for me:
package main
/*
void foo(int *len) { *len = 1234; }
*/
import "C"
func main() {
var x C.int
C.foo(&x)
println(x)
}
答案2
得分: 8
这里的问题是你有两种不同的类型。你有一个由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
中。
额外回答:int* len
确实与int *len
相同。
英文:
The issue here is you have two different types. You have an int
which is defined by your Go compiler and C.int
which is defined by your C compiler. Depending on the compilers and architecture these may be the same size. However, it is very possible that int
will be 64 bits in size and C.int
would be 32 bits.
In order for the compiler to enforce the type safety, it requires you to do an explicit conversion or define the type at initialization.
In your example, you do: x := 0
. This is the same as x := int(0)
. The int
is implied. Instead, you can do x := C.int(0)
.
However, I think the "cleaner" method would be to do what jnml recommended: var x C.int
. This does exactly the same thing but just looks nicer.
Later, you will most likely want to convert that C.int
back to an int
. This is easy to do with a conversion.
y := int(x)
This will convert x
to an int
and then copy that value into the newly initialized variable y
.
Bonus Anwser: int* len
is indeed the same as int *len
答案3
得分: 3
你需要一个unsafe.Pointer
的转换。
C.ccv_write(image.image, dst, (*C.int)(unsafe.Pointer(&x)), C.CCV_IO_PNG_FILE, 0)
英文:
You will need an unsafe.Pointer
cast.
C.ccv_write(image.image, dst, (*C.int)(unsafe.Pointer(&x)), C.CCV_IO_PNG_FILE, 0)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论