2017-06-22 20 views
0

私はCにdecalredはextern機能があります。構造体へのconstポインタに相当するcgo型は何ですか?

//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

関数 'goCallback'が' C'と 'Go'の両方で定義されているため、コンパイラは文句を言います。あなたが 'C'から' go'関数にアクセスできるようにするには、 '// export ...'が必要です。 'go'から' C'関数を使いたい場合は、// extern void ...で十分です。 – putu

+0

https://github.com/golang/go/wiki/cgo#function-variablesを見て、私は正しいことをしています。 'c'から' go'にアクセスするには、 '// extern宣言'//コメントをエクスポートします。 – tarrsalah

+0

申し訳ありませんが、私はあなたの質問に誤解しました。コンパイラーは、異なる署名を持つ2つの '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") 
} 

をあなたはC.clibvlc_event_tに互換性のあるgo型定義を知りたい場合は、-godefsオプションでcgoを実行する、すなわち

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

EDIT:
例の構造体を追加します。

+0

あなたの答えをありがとう、私は 'clibvlc_event_t'に' libvlc_event_t'のエイリアスをどうすればいいのだろうかと思いますか? – tarrsalah

+0

@tarrsalah実際に引数に 'const'修飾子がない場合、' Cstruct_libvlc_event_t'を通して 'C'構造体にアクセスできます。 'go'は' const'修飾子を持たないので、 'typedef'は一つの回避策です。ここで 'clibvlc_event_t'を選択して、この型に' const'修飾子があることを示します。 'libvlc_event_t'を使うことができます。別の解決策は 'const'修飾子なしで' C'に別のコールバック関数を作成することです。 – putu

+0

あなたの答えとあなたのコメントはとても役に立ちます。ありがとうございます。 – tarrsalah

関連する問題