2

現在、Cgo を使用して Go から C 関数を呼び出しています。Go で「写真を読む」の例を再現しようとしています。

ただし、C 関数の場合は、int* len引数が必要です (おまけの質問です。それは ? と同じint *lenですか)。これを読むと、これは整数へのポインタです。問題の関数はccv_writelibccv ライブラリのものです。完全な署名は次のとおりです。

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

正しい引数を渡す方法について何か考えはありますか?

4

3 に答える 3

9

これは私にとってはうまくいくようです:

package main

/*

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

*/
import "C"

func main() {
        var x C.int
        C.foo(&x)
        println(x)
}
于 2012-11-16T14:07:21.987 に答える
7

ここでの問題は、2 つの異なるタイプがあることです。GointコンパイラによってC.int定義された と、C コンパイラによって定義された があります。コンパイラとアーキテクチャによっては、これらは同じサイズになる場合があります。ただし、intサイズが 64 ビットでC.int32 ビットになる可能性は十分にあります。

コンパイラがタイプ セーフを適用するには、明示的な変換を行うか、初期化時に型を定義する必要があります。

あなたの例では、次のことを行いますx := 0。これは と同じx := int(0)です。intが暗示されています。代わりに、次のことができますx := C.int(0)

ただし、「よりクリーンな」方法は、jnmlが推奨することを行うことだと思います: var x C.int. これはまったく同じことを行いますが、見栄えが良くなります。


C.int後で、おそらくそれを に戻したいと思うでしょうint。これは、変換を使用して簡単に行うことができます。

y := int(x)

これは に変換xされ、intその値が新しく初期化された variable にコピーされますy


ボーナスAnwser:int* len確かに同じですint *len

于 2012-11-16T17:38:26.010 に答える
3

unsafe.Pointerキャストが必要になります。

C.ccv_write(image.image, dst, (*C.int)(unsafe.Pointer(&x)), C.CCV_IO_PNG_FILE, 0)
于 2012-11-16T14:53:09.933 に答える