struct_ 前缀与无前缀

yag*_*eek 2 c compilation go cgo

我目前正在编写一些基本的 cgo 代码。根据关于 Go to C 参考cgo 文档

要直接访问 struct、union 或 enum 类型,请在其前面加上 struct_、union_ 或 enum_ 前缀,如 C.struct_stat 中所示。

我对这句话的理解是,如果我有一个Foo用 C命名的结构体,我必须使用C.struct_FooGo 中的类型。

我写了一些 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)
}
Run Code Online (Sandbox Code Playgroud)

我遇到了一个编译错误,比如:

无法将 d.navilinkC(类型 *_Ctype_struct_NavilinkDevice)转换为类型 _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;
Run Code Online (Sandbox Code Playgroud)

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

每个 C 函数都需要一个指向NavilinkDeviceC 结构的指针作为最后一个参数。可以在此处找到 C 库的代码

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

Lia*_*lly 5

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

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

typedef struct{
    int a;
    char *b;
    ...
    char z[20];
 }Foo;
Run Code Online (Sandbox Code Playgroud)

在 C 中,您将Foo x在声明Fooso的实例时将 this 称为在 Cgo 中将其称为C.Foo.

您收到奇怪错误的原因是因为编译器没有您声明为 typedef 的结构的名称,因此它调用它_0.

在您的示例中,您的 Go 代码期待

struct Foo{
    int a;
    char *b;
    ...
    char z[20];
 };
Run Code Online (Sandbox Code Playgroud)

在 C 中,您将struct Foo x在声明Fooso的实例时将 this 称为在 Cgo 中将其称为C.struct_Foo.

额外有用的信息

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