簡體   English   中英

CGO:在 LPCWSTR 和字符串之間轉換

[英]CGO: Convert between LPCWSTR and string

我正在為一個使用LPCWSTR的所有字符串類型的庫編寫 CGO 綁定。 如何從C.LPCWSTR轉換為string ,反之亦然?

您應該能夠將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)

你一般不希望被路過的圍棋指針到你的C代碼,所以從字符串轉換為LPCWSTR時,你會想在頁頭C.解決辦法的內存從一個圍棋字符串轉換s可能看起來像:

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

可能還有一些 MFC 宏可以幫助轉換為 cstrings 和從 cstrings 轉換,您可以利用 C 中的簡單包裝函數來利用這些宏。這樣,您只需使用內置的C.CStringC.GoString就可以輕松地將數據復制進和出功能。

如果您確定輸入不包含空字節,您可以自己進行編碼:

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

作為在 C 中分配內存的另一種方法,可以調用 syscall.UTF16PtrFromString:

func Encode(s string) C.LPCWSTR {
    ptr, _ := syscall.UTF16PtrFromString(s)
    return C.LPCWSTR(unsafe.Pointer(ptr))
}

這假設您嘗試調用的 API(假設是 win32 API,因為您使用的是 LPCWSTR)沒有制作任何字符串指針的副本。 如果確實如此,如果 GoLang 的代碼范圍合適,則不分配 C 內存應該是安全的。

例如,下面的代碼行應該沒問題:

func DoSomeWindowsStuff(arg string) {
  CallWin32API(Encode(arg))
}

這里為字符串分配的內存應該一直存在,直到 CallWin32API() 返回。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM