为了账号安全,请及时绑定邮箱和手机立即绑定

有没有办法直接将gorang字符串复制到预分配的C字符缓冲区

有没有办法直接将gorang字符串复制到预分配的C字符缓冲区

Go
长风秋雁 2022-10-04 17:18:46
我有一个变量(但组合大小有上限)需要传递给C的GoStrings数量,我想尽可能便宜地做到这一点。我将多次执行此操作(因此可以考虑将重用的预分配缓冲区视为零成本)。我最初的方法是循环遍历 GoStrings,将每个 GoString 转换为 CString 并将其推送到 C。for _, str := range mystrings {   cstr := C.CString(str)   defer C.free(unsafe.Pointer(cstr))   C.push_str(pushStrFn, cstr)}当然,由于 以及 N 个 CGo 调用,这正在执行 N 堆分配 - 所有这些都不便宜。C.CString接下来是使用在开始时分配的时间在Go中构建一个大字符串,然后在单个CGo调用中将其传递给C,并带有一些长度信息。这是一个 CString 调用和一个 CGo 调用 - 这是一个实质性的改进。strings.Builderbuilder.Reset()for _, str := range mystrings {   builder.WriteString(str)}C.push_strs(pushStrsFn, C.CString(builder.String()))但是这种方法仍在执行不必要的复制!理想情况下,我想预先分配一大块内存,我可以将其传递给C,然后只需将字符串直接复制到C中,而无需使用大型GoString中介。我能够提前预先分配一个大数组,并迭代GoStrings中的字符,一次复制一个。这避免了中间复制,但比专用的字符串复制函数(如构建器的函数)慢得多。cCharArray := C.malloc(C.size_t(MAX_SIZE) * C.size_t(unsafe.Sizeof(uintptr(0))))goCharArray := (*[1<<30 - 1]C.char)(cCharArray)for _, str := range mystrings {   for i, c := range str {      goCharArray[offset+i] = C.char(c)   }}C.push_charArray(pushCharArrayFn, (*C.char)(cCharArray))有没有一种更快的方法来做到这一点,我错过了?我是否可以以某种方式将 C 缓冲区馈送到 ,或者使用字符串复制函数直接提供给 C 缓冲区?strings.Builder
查看完整描述

2 回答

?
繁星淼淼

TA贡献1775条经验 获得超11个赞

你试过吗,或者这个包装器在它上面?https://github.com/chai2010/cgo/blob/master/char.go#L61 .如果这速度不快,您可以尝试使用不安全将指向 Go 字符串的指针转换为 CString 指针。C.strncpy



查看完整回答
反对 回复 2022-10-04
?
胡说叔叔

TA贡献1804条经验 获得超8个赞

使用不安全的包从 C 分配的缓冲区中创建字节片。

然后,您可以直接复制到该切片中,也可以将其作为零长度的复切片粘贴到字节中。缓冲并使用写字符串。您必须小心不要超过原始容量,否则缓冲区会将数据复制到新的后备缓冲区。


查看完整回答
反对 回复 2022-10-04
  • 2 回答
  • 0 关注
  • 75 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信