2016-12-21 24 views
1

私はGo Windowsのsyscallライブラリを使用して、DLLの関数からデータを取得しています。これはすべて素晴らしいですが、CGOを使わずに、LPCTSTR(C文字列へのポインタ)を適切なGo文字列に変換する方法を理解できません。C文字列をCGOなしのGo文字列に変換

Windows上でのCGOコードの2つのオプション(クロスコンパイル、Windows上でのgccのインストール)はまだかなり複雑なので、可能な限りCGOを避けたいと思います。

+0

私は考えていません*何かハッキーをしないとCGO以外の簡単な方法があります。 CGOのgccは必要ありませんが、env var 'CC = 'を設定することでCGOのコンパイラを設定することができます。私はWindowsのcコンパイラについてはあまりよく分かりませんが、Windowsではenv varsが重要です。 –

+0

あなたは確かに文字列を変換できますが、問題はLPCTSTRが条件付きでLPCSTRまたはLPCWSTRのtypedefであることです。タイプを保証する方法はありますか? – JimB

+0

@JimB、はい、私は、文字列の型は私が "A"または "W"の2つのデータ型の接尾辞を持つ呼び出している関数によって暗示されていると思います。 – brooks94

答えて

2

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) 
+0

nice。文字列を必要としない限り、コピーが必要なのはなぜですか? – Mark

+1

@マーク:それを文字列に変換すると、暗黙的にバイトのコピーが作成されます。スライスを配列から直接返すと、元のメモリ位置を指します。この位置は後でアクセスするのが安全かもしれません。 – JimB

0

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 
} 
関連する問題