struct_ 前缀与无前缀

struct_ prefix vs no prefix

我目前正在编写一些基本的 cgo 代码。根据 cgo documention about Go to C references:

To access a struct, union, or enum type directly, prefix it with struct_, union_, or enum_, as in C.struct_stat.

我对这句话的理解是,如果我在C中有一个名为Foo的结构,我必须在Go中使用C.struct_Foo类型

我写了一些 Go 代码,例如:

package main

// #cgo LDFLAGS: -lnavilink -lserialport
// #cgo CFLAGS: -I/usr/local/include
// #include<navilink/navilink.h>
import "C"
import "errors"

func (d *Device) navilinkErrorToGoError() error {
    errorC := C.navilink_get_error_description(d.navilinkC)
    return errors.New(C.GoString(errorC))
    return nil
}

// Device représente une interface
// vers le port série connecté au GPS
type Device struct {
    navilinkC *C.struct_NavilinkDevice
}

// Open permettra au développeur d'ouvrir la communication
func (d *Device) Open(path string) error {
    res := C.navilink_open_device_from_name(C.CString(path), d.navilinkC)
    if res < 0 {
        return d.navilinkErrorToGoError()
    }
    return nil
}

// Close permettra au développeur de fermer la communication
func (d *Device) Close() {
    C.navilink_close_device(d.navilinkC)
}

我遇到了类似这样的编译错误:

cannot convert d.navilinkC (type *_Ctype_struct_NavilinkDevice) to type _Ctype_struct___1

C结构的定义如下:

typedef struct {
  struct sp_port* serial_port;
  struct sp_event_set* event_set;
  uint8_t buffer[NAVILINK_MAX_PACKET_SIZE];
  NavilinkInformation informations;
  int firmware_version;
  NavilinkPacket response_packet;
  int last_error_code;
} NavilinkDevice;

如果我使用 C.DeviceNavilink 而不是 C.DeviceNavilink 作为字段类型,编译成功。

每个 C 函数都期望一个指向 NavilinkDevice C 结构的指针作为最后一个参数。可以找到 C 库的代码 here

为什么上面的文档句子是因为你可以在不使用任何前缀的情况下引用C类型?两者有什么区别?

您将 C 结构声明为 typedef 而不是命名结构。

在你的 C 代码中你有这样的东西:

typedef struct{
    int a;
    char *b;
    ...
    char z[20];
 }Foo;

在 C 中,当声明 Foo 的一个实例时,您会把它称为 Foo x,所以在 Cgo 中,您会把它称为 C.Foo.

你得到奇怪错误的原因是因为编译器没有你声明的结构的名称只是一个 typedef,所以它调用它 _0.

在您的示例中,您的 Go 代码符合预期

struct Foo{
    int a;
    char *b;
    ...
    char z[20];
 };

在 C 中,当声明 Foo 的实例时,您将引用它作为 struct Foo x,因此在 Cgo 中,您将引用它作为 C.struct_Foo.

额外有用的信息

  • 如果您需要获取 typedef struct Cgo 的大小,请使用 C.sizeof_Foo
  • 要查看 Cgo 如何声明你的 C 结构的 Go 版本 运行 go tool cgo <go file> 并查看 _obj/_cgo_gotypes.go 文件