英文:
Convert C string to Go string without CGO
问题
我正在使用Go Windows syscall库从DLL中的函数中获取数据。这一切都很顺利,但是我无法找到一种方法将LPCTSTR(指向C字符串的指针)转换为适当的Go字符串,而不使用CGO。
如果可能的话,我想尽量避免使用CGO,因为在Windows上,CGO代码的两个选项(交叉编译和在Windows上安装gcc)仍然相当复杂。
英文:
I'm using the Go Windows syscall libraries to get data out of a function in a DLL. This all works great, but I can't figure out a way to convert a LPCTSTR (pointer to C String) into a proper Go string without using CGO.
I'd like to avoid CGO if at all possible, because the two options for CGO code on Windows (cross-compiling, and installing gcc on windows) are still fairly complex.
答案1
得分: 3
如果你有一个8位字符串,你可以将LPCTSTR指针转换为正确大小的[]byte
,并将其复制到一个新的字符串或切片中。
a := (*[1 << 30-1]byte)(unsafe.Pointer(lpctstr))
size := bytes.IndexByte(a[:], 0)
// 如果你只想要一个字符串
// goString := string(a[:size:size])
// 如果你想要一个指向原始内存位置的切片而不进行复制
// 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)
英文:
If you have an 8 bit string, you can convert the LPCTSTR pointer to a []byte
of the proper size, and copy it to a new string or slice.
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)
If the LPCTSTR points to an LPCWSTR which contains 16bit unicode characters, you can convert that with the utf16 package.
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)
答案2
得分: 1
如果您可以在没有CGO的情况下获得指向C字符串的指针,并且还可以获得字符串的长度,那么您可以首先从C字符串创建一个字节切片。
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
}
这段代码将创建一个字节切片 bytes
,并使用 reflect.SliceHeader
将其与 C 字符串关联起来。然后,将字符串的长度和指针分别赋值给 shdr.Len
和 shdr.Data
。最后,返回字节切片 bytes
。
英文:
If you can get a pointer to a cstring without CGO, and you can get the length of the string too, then perhaps you should create a byte slice from the cstring first.
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
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论