CGO; C函数有一个int指针参数,如何传递正确的类型?

huangapple go评论77阅读模式
英文:

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)

huangapple
  • 本文由 发表于 2012年11月16日 21:41:51
  • 转载请务必保留本文链接:https://go.coder-hub.com/13417789.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定