访问字符串的原始字节

时间:2018-03-23 16:03:14

标签: go cgo

我试图调用一个需要C字符串(char*)的C函数。我知道cgo documentation中记录的C.CString函数,但由于我调用的函数已经复制了,我试图避免使用Cstring个版本。

现在,我正在这样做,s是一个字符串

 var cs *C.char = (*C.char)( unsafe.Pointer(& []byte(s) [0]))

但我觉得[]bytes(s)正在制作自己的副本。是否可以获得char*

1 个答案:

答案 0 :(得分:4)

如果你这样做的次数足以令人担忧,那么将数据保持在切片中是非常明智的。

如果您确实想要访问字符串的地址,可以使用unsafe包将其转换为与字符串标头匹配的结构。使用reflect.StringHeader类型:

p := unsafe.Pointer((*(*reflect.StringHeader)(unsafe.Pointer(&s))).Data)

或者使用切片作为代理,因为它们都将数据指针和长度整数放在相同的字段位置

p := unsafe.Pointer(&(*(*[]byte)(unsafe.Pointer(&s)))[0])

或者因为数据指针是第一个,您可以单独使用uintptr

p := unsafe.Pointer(*(*uintptr)(unsafe.Pointer(&s)))

https://play.golang.org/p/ps1Py7Ax6QK

这些方法都不能保证在所有情况下或在Go的未来版本中都能正常工作,并且没有一个选项可以保证以空字符串结尾的字符串。

最好的,支持的选项是在cgo前导码中创建一个垫片以接受go字符串,并将其转换为*char。 CGO提供对以下功能的访问:

const char *_GoStringPtr(_GoString_ s);

请参阅文档中的Go references to C部分。