2 回答
TA贡献1877条经验 获得超6个赞
您已经分配了 C 内存来容纳许多单独的指针。每个单独的指针都可以设置为单独的值。就目前而言,这很好,但是正如您所指出的,这是一个问题,因为其本身具有指向Go-memory的指针 。a[index] = box
box
C.struct_Box
我试图在将C Box传递给C函数之前将其添加到数组中。
要从字面上做到这一点,你需要一个电话。如前所述,每个实例都需要一个。C.malloc
C.struct_Box
解决这个问题的方法是让我用C编写一个函数,它可以接收数组和创建结构所需的项,而我在C中做那部分?
虽然你可以尝试一下,但似乎...欠佳。
我试图尽量减少对C的调用次数,所以如果我可以从Go创建数组,那就太好了。真的很难知道如何安全地将数据数组传递到C中的函数。
C从来都不是真正安全的😀,但我怀疑你最好的选择是利用C实现“数组”的方式,这是一种穷人的切片。(或者,也许更准确地说,Go切片是一个“C数组”,做得对。请记住,切片在 Go 中作为三元素标头实现:
指向存储区域底部的指针;
存储区域内的当前长度;和
存储区域容量
然后,它可以保存某种类型的项的一些运行时计算的n个数。C的动态“数组”以相同的方式工作,只是没有适当的切片标头的安全性。
这意味着您可以编写 C 代码(前提是您可以控制此 C 代码),以获取指向存储区域基数的指针,以及计算该区域中 n 个项目数的 or 值。此类函数的签名是:int
size_t
void f(T *base, size_t n);
其中 是项目数。(如果还想提供容量,请根据需要添加一秒钟,但如果内存具有容量,并且函数对其进行修改以包含不同数量的项目,则函数必须返回新数量的项目(即不会返回),或者本身必须通过引用或类似的东西来提供。n
size_t
f
void
n
在这种情况下,如果可以安排 C 代码以获取指向 -es 中的第一个指针(而不是指向 -es 的第一个指针),则可以在单个调用中分配该指针。n
struct Box
n
struct Box
C.malloc
如果您无法返工C代码,则至少会遇到两个调用。但是,您可以再次将所有es分配到一个中,并使它们全部相邻 - 即C“数组”/穷人的切片 - 然后使每个指针指向下一个:C.malloc
struct Box
C.malloc
struct Box
cArray := C.malloc(C.size_t(len(fd.Faces)) * C.size_t(unsafe.Sizeof(uintptr(0))))
defer C.free(unsafe.Pointer(cArray))
cBoxes := C.malloc(C.size_t(len(fd.Faces)) * C.size_t(unsafe.Sizeof(C.struct_Box)))
defer C.free(unsafe.Pointer(cBoxes))
a := (*[1<<30 - 1]*C.struct_Box)(cArray)
b := (*[1<<30 - 1]C.struct_Box)(cBoxes)
for index, value := range fd.GetFaceRectangles() {
b[index] = C.struct_Box{
left: C.int(value.Min.X),
top: C.int(value.Min.Y),
right: C.int(value.Max.X),
bottom: C.int(value.Max.Y),
}
a[index] = &b[index]
}
cBoxCount := C.int(len(fd.Faces))
ret := C.facerec_compute_multi(rec.ptr, cImgData, cLen, &a[0], cBoxCount)
(我试图在这里保持代码结构尽可能相似,这是未经测试的,因为我没有一些部分。
题外话:你有 和 这里的代码假设 a 的迭代次数总是 。我之所以提出这一点,是因为我做出了同样的假设,除了你的例子之外,没有任何东西可以支持它。len(fd.Faces)fd.GetFaceRectangles()for ... range fd.GetFaceRectangles()len(fd.Faces)
TA贡献1850条经验 获得超11个赞
在Slack通道上的一些帮助下,我最终得到了这个,只是直接添加结构而不是指针。
// Create an array in C
arr := C.malloc(C.size_t(len(fd.Faces)) * C.sizeof_Box)
defer C.free(unsafe.Pointer(arr))
var boxes []C.struct_Box
hdr := (*reflect.SliceHeader)(unsafe.Pointer(&boxes))
hdr.Data, hdr.Cap, hdr.Len = uintptr(arr), len(fd.Faces), len(fd.Faces)
for i, v := range fd.GetFaceRectangles() {
boxes[i] = C.struct_Box{
left: C.int(v.Min.X),
top: C.int(v.Min.Y),
right: C.int(v.Max.X),
bottom: C.int(v.Max.Y),
}
}
cBoxCount := C.int(len(fd.Faces))
ret := C.facerec_compute_multi(rec.ptr, cImgData, cLen, &(boxes[0]), cBoxCount)
- 2 回答
- 0 关注
- 85 浏览
添加回答
举报