struct_前缀vs无前缀

时间:2018-03-16 15:09:09

标签: c go compilation cgo

我目前正在撰写一些基本的cgo代码。根据{{​​3}}:

  

要直接访问struct,union或enum类型,请在其前面加上   struct_,union_或enum_,如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)
}

我遇到编译错误,如:

  

无法将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;

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

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

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

1 个答案:

答案 0 :(得分:3)

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

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

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

在C中,当您声明Foo x的实例时,您会将其称为Foo,因此在Cgo中您将其称为C.Foo

您得到奇怪错误的原因是因为编译器没有您声明为typedef的结构的名称,因此它将其称为_0

在您的示例中,您的Go代码需要

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

在C中,当您声明struct Foo x的实例时,您会将其称为Foo,因此在Cgo中您将其称为C.struct_Foo

额外有用的信息

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