Search code examples
gocgo

What is the cgo type equivalent to a const pointer to a struct?


I have an extern function decalred in C:

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

To be defined in go:

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

When compiling the code, I get type conflicting errors

# 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*);
             ^~~~~~~~~~

What is the go equivalent to const struct libvlc_event_t*?


Solution

  • Create type alias to the struct with typedef as follows:

    /*
    
    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")
    }
    

    If you want to know go type definition which is compatible to C.clibvlc_event_t, run cgo with -godefs options, i.e.

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

    For example, if the struct is defined as in 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;
    };
    

    then, the compatible struct in go will be:

    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:
    Add example struct.