2017-07-27 106 views
0

我期待將[32]C.wchar_t轉換爲去字符串。GoLang轉換C.wchar_t去字符串

陣列被定義爲dll如下我說於:

typedef struct myStruct { 
    WCHAR someString[32]; 
} 

我定義中去該結構如下:

type myStruct struct { 
    someString [32]C.wchar_t 
} 

我在dll的方法:

DLLINTERFACE HRESULT __stdcall GetMyStruct (myStruct* ptrMyStruct); 

該方法將填充someString字段myStruct

我打電話,像這樣的方法(這是正常工作,我想,我一直沒能看到someString內容):

func getMyStruct() (*myStruct, uintptr) { 
    var getMyStruct = dll.MustFindProc("GetMyStruct") 
    var args = new(myStruct) 
    ret, _, _ := getMyStruct .Call(uintptr(unsafe.Pointer(args))) 

    fmt.Printf("Return: %d\n", (int)(ret)) 
    return args, ret 
} 

我需要someString轉換爲去串。我曾嘗試使用"github.com/GeertJohan/cgo.wchar",但它沒有將[]C.whar_t轉換爲字符串的方法。

目前我不確定我的結構是否正確。我也不確定在將它發送到dll之前是否正確初始化myStruct

任何幫助將不勝感激。

回答

1

在Windows上,wchar_t通常是UTF-16(小端)。它們通常不以BOM(它存在,因此解碼器可以檢測它們是以大的還是小的端存形式存儲)開始。

有一個utf16包,但這隻能翻譯個別符文。但是,有一個額外的unicode文本編碼包可以提供幫助。

你可能會做這樣的事:

dec:=unicode.UTF16(unicode.LittleEndian,unicode.UseBOM).NewDecoder() 
out,err:= dec.Bytes(([]byte)(unsafe.Pointer(args.someString))) 
if err!=nil { 
    //handle error 
} 
// Strings are null terminated, only want content up to null byte 
i:=bytes.IndexByte(out,0) 
if i==-1 { 
    i = len(out) 
} 
s:=string(out[:i]) 

不過,我會忍不住宣佈someString[64]byte這是字節數是32個字符(16個叮咬=每個字符2個字節)需要。這將避免不安全的類型轉換,但是應該如上所述工作。

所以上面的代碼意味着作爲示例&不一定工作,我這樣做了我的頭頂 - 使用後果自負:-)

0

看來GeertJohan的圖書館有沒有已針對最近的cgo更改進行了更新,但叉已經嘗試使用github.com/vitaminwater/cgo.wchargodoc)。

如果C函數寫入C類型,則傳遞C類型的變量。

A(躲閃)例如:

package main 

/* 
#include <wchar.h> 
#include <string.h> 

typedef struct myStruct { 
    wchar_t someString[32]; 
} myStruct; 

wchar_t sample[6] = {0x0048, 0x0069, 0x0020, 0x4e16, 0x754c, 0}; 

void writeSample(myStruct *m) { 
    memcpy(m->someString, &sample, sizeof(wchar_t) * 6); 
} 
*/ 
import "C" 
import (
    "fmt" 
    "log" 
    "unsafe" 

    "github.com/vitaminwater/cgo.wchar" 
) 

func main() { 

    m := C.myStruct{} 

    C.writeSample(&m) 

    s, err := wchar.WcharStringPtrToGoString(unsafe.Pointer(&m.someString)) 
    if err != nil { 
     log.Fatal(err) 
    } 
    fmt.Println(s) 
} 

此輸出:

Hi 世界