【问题标题】:cgo: How to pass struct array from c to gocgo:如何将结构数组从 c 传递到 go
【发布时间】:2019-06-08 07:50:51
【问题描述】:

C部分:

struct Person {...}
struct Person * get_team(int * n)

Go 部分:

n := C.int(0)
var team *C.struct_Person = C.get_team(&n)
defer C.free(unsafe.Pointer(team))

我可以通过这种方式获取数组的第一个元素。但是如何获得包含 n 个元素的整个数组呢? 以及如何安全地释放它们?

【问题讨论】:

  • 您可能希望/需要将 C 指针(以及隐含长度 n??)转换为 Go 切片。这很重要,也许是一些使用反射的支持代码?

标签: go cgo


【解决方案1】:

首先,即使您使用的是 Go,当您添加 cgo 时,不再有任何“安全”。由您决定何时以及如何释放内存,就像使用 C 编程一样。

在go中使用C数组最简单的方法是通过数组将其转换为切片:

team := C.get_team()
defer C.free(unsafe.Pointer(team))
teamSlice := (*[1 << 30]C.struct_Person)(unsafe.Pointer(team))[:teamSize:teamSize]

实际上并没有分配最大大小的数组,但 Go 需要恒定大小的数组,而 1&lt;&lt;30 将足够大。该数组会立即转换为切片,并正确设置长度和容量。

【讨论】:

  • 不错!有用!但我无法得到数组切片部分 [:teamSize:teamSzie] 。我用 [:teamSize] 替换它,它的工作原理相同。为什么要加倍团队规模?
  • @crackcell:切片表示法中的第三个字段(第一个为 0,此处可以省略)设置切片容量 (Slice Expressions)。您需要它来防止可能的缓冲区溢出到数组之外的内存中。
  • @JimB:现在我有足够的声誉来写评论:您能否更正您的答案并在C.free 之前添加一个defer(请参阅我对这个问题的回答以了解其他选择) .您编写它的方式,内存在使用前被释放,即使用teamSlice时保证无效的内存访问。
  • 代码sn-p最后一行不应该是C.struct_Person而不是C.team吗?这对我有用teamSlice := (*[1 &lt;&lt; 30]C.struct_Person)(unsafe.Pointer(team))[:teamSize:teamSize]
猜你喜欢
  • 2021-09-13
  • 1970-01-01
  • 1970-01-01
  • 2023-03-17
  • 1970-01-01
  • 2011-06-01
  • 2011-01-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多