cgo类型相当于指向结构的常量指针是什么?

cgo类型相当于指向结构的常量指针是什么?,go,cgo,Go,Cgo,我在C中标记了一个外部函数: //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/lib

我在
C
中标记了一个外部函数:

//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
const struct libvlc\u event.*
等效的是什么?

使用
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>
然后,
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{}))
编辑:

添加示例结构。

编译器会抱怨,因为函数
goCallback
C
Go
中都定义了。当您想从
C
访问
go
功能时,需要使用
//导出…
。如果你想从
go
使用
C
函数,
//外部无效…
就足够了。看看,我做得对,从
C
访问
go
需要
//外部声明
//导出注释
。对不起,我误解了你的问题。编译器抱怨,因为有两个签名不同的
goCallback
函数。我写了一个答案,希望能有帮助。谢谢你的回答,我只是想知道为什么我应该把
libvlc_event_t
化名为
clibvlc_event_t
?@tarsalah实际上,如果参数没有
const
限定符,你可以通过
C.struct\libvlc_event_t
访问
C
结构。由于
go
没有
const
限定符,
typedef
是一种解决方法。在这里,我选择
clibvlc\u event\t
表示该类型具有
const
限定符。您可以使用
libvlc\u event\t
。另一个解决方案是在
C
中创建另一个回调函数,而不使用
const
限定符。您的回答和评论非常有用,谢谢。
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{}))