私はGo Windowsのsyscallライブラリを使用して、DLLの関数からデータを取得しています。これはすべて素晴らしいですが、CGOを使わずに、LPCTSTR(C文字列へのポインタ)を適切なGo文字列に変換する方法を理解できません。C文字列をCGOなしのGo文字列に変換
Windows上でのCGOコードの2つのオプション(クロスコンパイル、Windows上でのgccのインストール)はまだかなり複雑なので、可能な限りCGOを避けたいと思います。
私はGo Windowsのsyscallライブラリを使用して、DLLの関数からデータを取得しています。これはすべて素晴らしいですが、CGOを使わずに、LPCTSTR(C文字列へのポインタ)を適切なGo文字列に変換する方法を理解できません。C文字列をCGOなしのGo文字列に変換
Windows上でのCGOコードの2つのオプション(クロスコンパイル、Windows上でのgccのインストール)はまだかなり複雑なので、可能な限りCGOを避けたいと思います。
。
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)
16ビットのUnicode文字が含まれているLPCWSTRへLPCTSTRポイントの場合は、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からバイトスライスを作成する必要があります。あなたは8ビット列を持っている場合は、適切なサイズの[]byte
にLPCTSTRポインタを変換し、新しい文字列またはスライスにコピーすることができます
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以外の簡単な方法があります。 CGOのgccは必要ありませんが、env var 'CC = 'を設定することでCGOのコンパイラを設定することができます。私はWindowsのcコンパイラについてはあまりよく分かりませんが、Windowsではenv varsが重要です。 –
あなたは確かに文字列を変換できますが、問題はLPCTSTRが条件付きでLPCSTRまたはLPCWSTRのtypedefであることです。タイプを保証する方法はありますか? – JimB
@JimB、はい、私は、文字列の型は私が "A"または "W"の2つのデータ型の接尾辞を持つ呼び出している関数によって暗示されていると思います。 – brooks94