CGO:在LPCWSTR和字符串之间转换

时间:2016-08-12 21:27:21

标签: go cgo lpcwstr

我正在为一个库使用LPCWSTR为其所有字符串类型编写CGO绑定。如何从C.LPCWSTR转换为string,反之亦然?

3 个答案:

答案 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)
}

https://golang.org/pkg/unicode/utf16