2 votes

CGO ; La fonction C a un argument pointeur int, comment passer le type correct ?

Actuellement, j'utilise Cgo pour appeler des fonctions C depuis Go. J'essaie de recréer le Lire une photo exemple en Go.

Une des fonctions C, cependant, s'attend à une int* len (question bonus ; est-ce la même chose que int *len ?). D'après ce que je lis, il s'agit d'un pointeur vers un entier. La fonction en question est ccv_write de la bibliothèque libccv. Sa signature complète est :

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

L'extrait de code correspondant est le suivant :

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)
}

L'exemple ci-dessus génère l'erreur de compilation suivante : cannot convert &x (type *int) to type *_Ctype_int

Une idée sur la façon de passer le bon argument ?

9voto

zzzz Points 23017

Cela semble fonctionner pour moi :

package main

/*

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

*/
import "C"

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

7voto

Stephen Weinberg Points 12682

Le problème ici est que vous avez deux types différents. Vous avez un int qui est défini par votre compilateur Go et C.int qui est défini par votre compilateur C. En fonction des compilateurs et de l'architecture, ils peuvent avoir la même taille. Cependant, il est très possible que int aura une taille de 64 bits et C.int serait de 32 bits.

Pour que le compilateur applique la sécurité de type, il vous demande d'effectuer une conversion explicite ou de définir le type à l'initialisation.

Dans votre exemple, vous le faites : x := 0 . C'est la même chose que x := int(0) . El int est implicite. Au lieu de cela, vous pouvez faire x := C.int(0) .

Cependant, je pense que la méthode la plus "propre" serait de faire ce que jnml a recommandé : var x C.int . Cela fait exactement la même chose, mais c'est plus joli.


Plus tard, vous voudrez certainement convertir cette C.int de retour à un int . C'est facile à faire avec une conversion.

y := int(x)

Cela permettra de convertir x à un int et ensuite copier cette valeur dans la variable nouvellement initialisée y .


Bonus Anwser : int* len est bien la même chose que int *len

3voto

jimt Points 7028

Vous aurez besoin d'un unsafe.Pointer la distribution.

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X