我使用Go Windows的syscall類庫將數據從DLL中的某個函數中取出。這一切都很好,但我不知道如何將LPCTSTR(指向C字符串的指針)轉換爲合適的Go字符串,而不使用CGO。將C字符串轉換爲不含CGO的字符串
如果可能的話,我想盡量避免CGO,因爲Windows上CGO代碼的兩個選項(交叉編譯和在窗口上安裝gcc)仍然相當複雜。
我使用Go Windows的syscall類庫將數據從DLL中的某個函數中取出。這一切都很好,但我不知道如何將LPCTSTR(指向C字符串的指針)轉換爲合適的Go字符串,而不使用CGO。將C字符串轉換爲不含CGO的字符串
如果可能的話,我想盡量避免CGO,因爲Windows上CGO代碼的兩個選項(交叉編譯和在窗口上安裝gcc)仍然相當複雜。
如果你有一個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,您可以轉換與UTF-16封裝。
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)
如果你可以在沒有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
}
我不*認爲*有一個簡單的方法,除了CGO之外,沒有做一些黑客行爲。你不需要gcc來處理CGO,你可以通過設置env var'CC ='來設置CGO的編譯器。我對windows的c編譯器知之甚少,或者對於windows的env vars。 –
你當然可以轉換字符串,但問題是LPCTSTR有條件地是LPCSTR或LPCWSTR的typedef。你有什麼方法來確保類型? – JimB
@JimB,是的,我認爲字符串的類型是由我調用的函數隱含的,對於這兩種類型的數據有一個「A」或「W」後綴。 – brooks94