【问题标题】:What is the cgo type equivalent to a const pointer to a struct?什么是 cgo 类型,相当于指向结构的 const 指针?
【发布时间】:2017-06-23 10:39:16
【问题描述】:

我在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_event_t*

【问题讨论】:

  • 编译器抱怨因为函数goCallbackCGo 中都定义了。当您希望从C 访问您的go 函数时,需要//export ...。如果你想使用go中的C函数,//extern void ...就足够了。
  • 看看github.com/golang/go/wiki/cgo#function-variables,我做对了,从c访问go需要//extern declaration//export comment
  • 对不起,我误解了你的问题。编译器抱怨,因为有两个 goCallback 具有不同签名的函数。我写了一个答案,希望对您有所帮助。

标签: go cgo


【解决方案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{}))

编辑:
添加示例结构。

【讨论】:

  • 感谢您的回答,我只是想知道为什么要将libvlc_event_t 别名为clibvlc_event_t
  • @tarrsalah 实际上,如果参数没有const 限定符,您可以通过C.struct_libvlc_event_t 访问C 结构。由于go 没有const 限定符,typedef 是一种解决方法。这里我选择clibvlc_event_t 表示这个类型有const 限定符。您可以使用libvlc_event_t。另一种解决方案是在 C 中创建另一个回调函数,而不使用 const 限定符。
  • 你的回答和你的cmets非常有帮助,谢谢。
猜你喜欢
  • 2022-11-23
  • 2010-09-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-11-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多