什么是cgo类型等同于指向结构的const指针?

问题描述:

我有一个外部函数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

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