2015-11-14 3 views
5

私はこのようなsecur32.dllからGetUserNameExを呼び出すしようとしている:Golang:どうやってcgoなしでwin32 APIを呼び出せますか?

dll, err := syscall.LoadDLL("secur32.dll") 
if err != nil { 
    log.Fatal(err) 
} 
defer dll.Release() 

GetUserNameEx, err := dll.FindProc("GetUserNameExW") 
if err != nil { 
    log.Fatal(err) 
} 
arr := make([]uint8, 256) 
var size uint 
GetUserNameEx.Call(3, uintptr(unsafe.Pointer(&arr[0])), uintptr(unsafe.Pointer(&size))) 
fmt.Println(arr) 
fmt.Println(size) 

このコードは罰金コンパイルが、GetUserNameEx.Call()は失敗します。なぜ私はUserNameを得ることができないのか分からない。誰か助けてくれますか?

答えて

4

sizeは、イン・アウト・パラメータです。コールをするときには、それをバッファのサイズ(arr)に設定する必要があります。また、そのタイプはPULONGですので、Goでuint32を使用してください。 Windows PULONGタイプはULONG(範囲は0..4294967295です)へのポインタです。 sourceを参照してください。

またCall()戻り値3:

func (p *Proc) Call(a ...uintptr) (r1, r2 uintptr, lastErr error) 

ストア返さlastErrし、それを印刷します。あなたは、以前のエラーを見つけるだろう、そうしただろう:

_, _, lastErr := GetUserNameEx.Call(
    3, uintptr(unsafe.Pointer(&arr[0])), uintptr(unsafe.Pointer(&size))) 

fmt.Println(lastErr) 

プリント:

More data is available. 

これは、より多くのデータは、あなたが渡すバッファに収まるものよりも利用可能であることを意味する - いうか - でイン・アウト・パラメーターsizeで指定したサイズ(0sizeとして渡しました)。この場合

arr := make([]uint8, 256) 
var size uint32 = uint32(len(arr))/2 - 1 
_, _, lastErr := GetUserNameEx.Call(
    3, uintptr(unsafe.Pointer(&arr[0])), uintptr(unsafe.Pointer(&size))) 

fmt.Println(lastErr) 
fmt.Println(string(arr)) 
fmt.Println(arr) 
fmt.Println(size) 

lastErrは次のようになります:コード(サイズ計算の終了'\0'バイト/文字を伴うユニコードに2分割に注意し、マイナス1)作業

The operation completed successfully. 

エラーを正しく処理するには:

例:

r1, _, lastErr := GetUserNameEx.Call(
    3, uintptr(unsafe.Pointer(&arr[0])), uintptr(unsafe.Pointer(&size))) 

if r1 == 0 { 
    fmt.Println("ERROR:", lastErr.Error()) 
    return 
} 
// No error, proceed to print/use arr 
+0

>サイズはイン・アウト・パラメータです。 omgわかりません。ありがとうicza、今私のコードは正常に動作します。 – enugami

+0

@エヌガミ編集されたコードを参照してください。エラー処理が追加され、エラーの検出に大きく役立ちます。 – icza

関連する問題