将C字符串转换为不带CGO的Go字符串

时间:2016-12-21 16:03:12

标签: c go cgo

我使用Go Windows系统调用库从DLL中的函数中获取数据。这一切都很好,但我无法找到一种方法将LPCTSTR(指向C String的指针)转换为正确的Go字符串而不使用CGO

我想尽可能避免使用CGO,因为Windows上的两个CGO代码选项(交叉编译,在Windows上安装gcc)仍然相当复杂。

2 个答案:

答案 0 :(得分:3)

如果您有一个8位字符串,则可以将LPCTSTR指针转换为适当大小的[]byte,并将其复制到新的字符串或切片。

a := (*[1 << 30-1]byte)(unsafe.Pointer(lpctstr))
size := bytes.IndexByte(a[:], 0)
// if you just want a string
// goString := string(a[:size:size])

// if you want a slice pointing to the original memory location without a copy
// goBytes := a[:size:size]

goBytes := make([]byte, size)
copy(goBytes, a)

如果LPCTSTR指向包含16位unicode字符的LPCWSTR,则可以使用utf16包进行转换。

a := (*[1 << 30-1]uint16)(unsafe.Pointer(lpctstr))
size := 0
for ; size < len(a); size++ {
    if a[size] == uint16(0) {
        break
    }
}   
runes := utf16.Decode(a[:size:size])
goString := string(runes)

答案 1 :(得分:1)

如果你可以在没有CGO的情况下获得指向cstring的指针,并且你也可以得到字符串的长度,那么也许你应该首先从cstring创建一个字节切片。

import (
    "reflect"
    "unsafe"
)

func ToByteSlice() []byte {
    var bytes []byte

    shdr := (*reflect.SliceHeader)(unsafe.Pointer(&bytes))
    shdr.Cap = int(stringlen)
    shdr.Len = int(stringlen)
    shdr.Data = uintptr(unsafe.Pointer(cpointer))

    return bytes
}