我正在为一个库使用LPCWSTR
为其所有字符串类型编写CGO绑定。如何从C.LPCWSTR
转换为string
,反之亦然?
答案 0 :(得分:2)
你应该能够"演员" LPCWSTR
为[]uint16
,并使用utf16
包解码字符
// take a C.wstr pointer, and convert it to a go slice
// `sz` is the length of the LPCWSTR
wstr := (*[1 << 30-1]uint16)(unsafe.Pointer(C.wstr))[:sz:sz]
runes := utf16.Decode(wstr)
goString := string(runes)
您通常不希望将Go指针传递给您的C代码,因此在从字符串转换为LPCWSTR时,您需要在C中分配内存。从Go字符串转换的解决方案{ {1}}可能看起来像:
s
可能还有一些MFC宏可以帮助转换为cstrings和cstrings,你可以利用C中的简单包装函数。这样你只需使用内置{{1}就可以轻松地复制数据。 }和func Encode(s string) C.LPCWSTR {
wstr := utf16.Encode([]rune(s))
p := C.calloc(C.size_t(len(wstr)+1), C.sizeof_uint16_t)
pp := (*[1 << 30]uint16)(p)
copy(pp[:], wstr)
return (C.LPCWSTR)(p)
}
函数。
答案 1 :(得分:1)
作为在C中分配内存的一种替代方法,可以只调用syscall.UTF16PtrFromString:
func Encode(s string) C.LPCWSTR {
ptr, _ := syscall.UTF16PtrFromString(s)
return C.LPCWSTR(unsafe.Pointer(ptr))
}
这假定您要调用的API(由于您正在使用LPCWSTR而应该是win32 API)不会对字符串指针进行任何复制。如果确实如此,那么在GoLang的代码范围合适的情况下,不分配C内存应该是安全的。
例如,下面的代码应该可以:
func DoSomeWindowsStuff(arg string) {
CallWin32API(Encode(arg))
}
这里分配给字符串的内存应保留到CallWin32API()返回为止。
答案 2 :(得分:1)
如果您确定输入不包含空字节,则可以进行编码 自己:
import (
// #include <windows.h>
"C"
"unicode/utf16"
"unsafe"
)
func PtrFromString(s string) C.LPCWSTR {
r := []rune(s + "\x00")
e := utf16.Encode(r)
p := unsafe.Pointer(&e[0])
return (C.LPCWSTR)(p)
}