【问题标题】:struct_ prefix vs no prefixstruct_ 前缀与无前缀
【发布时间】:2018-03-16 23:46:36
【问题描述】:

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

要直接访问结构、联合或枚举类型,请在其前面加上前缀 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库的代码可以找到here

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

【问题讨论】:

  • 请发送minimal reproducible example。如果Foo 只是一个结构,那么void will_allocate_foo(Foo *foo){ 声明无效。这例如运行良好:play.golang.org/p/WSARkds3-ZE
  • 我不确定为什么 C 声明无效?
  • 如果Foo 是一个命名结构,那么你必须在类型前面加上struct,就像我的例子一样。
  • 我更新了提供的代码。在原始 C 源代码中,我使用了 typedef 而不是命名结构。

标签: c go compilation cgo


【解决方案1】:

您将 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 &lt;go file&gt; 并查看 _obj/_cgo_gotypes.go 文件

【讨论】:

  • 感谢您的解释。 cgo 文档对我来说不够清楚。
猜你喜欢
  • 2016-02-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-01-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多