2017-06-22 1 views
0

J'ai une fonction extern decalred dans C:Quel est le type de cgo équivalent à un pointeur const à une structure?

//extern void goCallback(const struct libvlc_event_t*, void*); 

A définir dans go:

//export goCallback 
func goCallback(event unsafe.Pointer, userData unsafe.Pointer) { 
    log.Fatal("TODO goCallback") 
} 

Lors de la compilation du code, je reçois les erreurs de type conflit

# github.com/tarrsalah/libvlc-go 
In file included from $WORK/github.com/tarrsalah/libvlc-go/_obj/_cgo_export.c:3:0: 
cgo-gcc-export-header-prolog:42:13: error: conflicting types for ‘goCallback’ 
In file included from $WORK/github.com/tarrsalah/libvlc-go/_obj/_cgo_export.c:3:0: 
../../../tarrsalah/libvlc-go/event_manager.go:6:13: note: previous declaration of ‘goCallback’ was here 
//extern void goCallback(const struct libvlc_event_t*, void*); 
      ^~~~~~~~~~ 
/tmp/go-build855229382/github.com/tarrsalah/libvlc-go/_obj/_cgo_export.c:17:6: error: conflicting types for ‘goCallback’ 
void goCallback(void* p0, void* p1) 
     ^~~~~~~~~~ 
In file included from $WORK/github.com/tarrsalah/libvlc-go/_obj/_cgo_export.c:3:0: 
../../../tarrsalah/libvlc-go/event_manager.go:6:13: note: previous declaration of ‘goCallback’ was here 
//extern void goCallback(const struct libvlc_event_t*, void*); 
      ^~~~~~~~~~ 

Quelle est le go équivalent à const struct libvlc_event_t*?

+0

Le compilateur se plaint car la fonction 'goCallback' est définie à la fois dans' C' et dans 'Go'. Le '// export ...' est nécessaire lorsque vous voulez que votre fonction 'go' soit accessible depuis' C'. Si vous voulez utiliser la fonction 'C' de' go', // // extern void ... 'est suffisant. – putu

+0

En regardant les https://github.com/golang/go/wiki/cgo#function-variables, je le fais bien, accéder à un 'go' à partir de' c' nécessite à la fois la '// déclaration extern' et le // commentaire d'exportation. – tarrsalah

+0

Je suis désolé, j'ai mal compris votre question. Le compilateur se plaint parce qu'il y a deux fonctions 'goCallback' avec une signature différente. J'ai écrit une réponse, j'espère que ça aide. – putu

Répondre

1

Créer un alias de type à la struct avec typedef comme suit:

/* 

typedef const struct libvlc_event_t clibvlc_event_t; 
extern void goCallback(clibvlc_event_t*, void*); 
*/ 
import "C" 

//export goCallback 
func goCallback(event *C.clibvlc_event_t, userData unsafe.Pointer) { 
    log.Fatal("TODO goCallback") 
} 

Si vous voulez savoir la définition de type go qui est compatible avec C.clibvlc_event_t, exécutez cgo avec -godefs les options, à savoir

go tool cgo -godefs <YOUR-GO-FILE> 

Par exemple, si la structure est définie en tant que https://docs.libreoffice.org/avmedia/html/Types_8hxx_source.html

struct libvlc_event_t 
{ 
    int type; // event type 
    void *p_obj; // object emitting that event 

    union // so far we don't need this. 
    { 
    struct { 
     const char *dummy1; 
     const char *dummy2; 
     } padding; 
    } u; 
}; 

puis, la struct compatible go sera:

type VLCEvent struct { 
    Type  int32 
    Pad_cgo_0 [4]byte 
    Obj  *byte 
    U   [16]byte 
} 

//Cast C struct to Go struct 
ev := (*VLCEvent)(unsafe.Pointer(event)) 

//Cast Go struct to C struct 
p := (*C.clibvlc_event_t)(unsafe.Pointer(&VLCEvent{})) 

EDIT:
Ajouter struct exemple.

+0

Merci pour votre réponse, je me demande juste pourquoi devrais-je alias 'libvlc_event_t' à' clibvlc_event_t'? – tarrsalah

+0

@tarrsalah En fait, si l'argument n'a pas de qualificatif 'const', vous pouvez accéder à la structure' C' par l'intermédiaire de 'C.struct_libvlc_event_t'. Puisque 'go' n'a pas de qualificatif' const', 'typedef' est une solution de contournement. Ici, je choisis 'clibvlc_event_t' pour indiquer que ce type a le qualificateur' const'. Vous pouvez utiliser 'libvlc_event_t'. Une autre solution consiste à créer une autre fonction de rappel dans 'C' sans qualificateur' const'. – putu

+0

Votre réponse et vos commentaires sont très utiles, merci. – tarrsalah