2017-06-22 46 views
0

我有一個外部函數decalred在C什麼是cgo類型等同於指向結構的const指針?

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

go定義:

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

當編譯代碼時,我得到類型衝突的錯誤

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

是什麼go相當於​​3210?

+0

編譯器抱怨,因爲在'C'和'Go'中都定義了'goCallback'函數。當你希望你的'go'函數可以從'C'訪問時,需要'// export ...'。如果你想從'go'使用'C'功能,'// extern void ...'就足夠了。 – putu

+0

看一下https://github.com/golang/go/wiki/cgo#function-variables,我做得很對,從'c'訪問'go'需要'// extern聲明'和'//註釋'。 – tarrsalah

+0

對不起,我誤解了你的問題。編譯器抱怨,因爲有兩個具有不同簽名的'goCallback'函數。我寫了一個答案,希望它有幫助。 – putu

回答

1

typedef創建類型別名的結構如下:

/* 

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

如果你想知道go類型定義,它是C.clibvlc_event_t兼容,運行cgo-godefs選項,即

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

例如,如果結構被定義爲如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; 
}; 

然後,在go兼容結構將是:

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

編輯:
添加示例結構。

+0

感謝您的回答,我只是想知道爲什麼要將'libvlc_event_t'別名到'clibvlc_event_t'? – tarrsalah

+0

@tarrsalah實際上,如果參數沒有'const'限定符,則可以通過'C.struct_libvlc_event_t'訪問'C'結構。由於'go'沒有'const'限定符,'typedef'是一種解決方法。在這裏,我選擇'clibvlc_event_t'來表示這個類型具有'const'限定符。你可以使用'libvlc_event_t'。另一種解決方法是在'C'中創建另一個沒有const限定符的回調函數。 – putu

+0

您的回答和您的意見非常有幫助,謝謝。 – tarrsalah

相關問題