GoLang将C.wchar_t转换为字符串

时间:2017-07-27 07:38:40

标签: c++ go dll

我希望将[32]C.wchar_t转换为go字符串。

数组在我正在谈论的dll中定义如下:

typedef struct myStruct {
    WCHAR someString[32];
}

我按照以下方式定义结构:

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

我在dll

中有一个方法
DLLINTERFACE HRESULT __stdcall GetMyStruct (myStruct* ptrMyStruct);

此方法将填充someString的{​​{1}}字段。

我正在调用这样的方法(这是正常的,我认为,我无法看到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 } 转换为go字符串。我已尝试使用someString,但它没有将"github.com/GeertJohan/cgo.wchar"转换为字符串的方法。

目前我不确定我的go结构是否正确。我还不确定在将[]C.whar_t发送到dll之前是否正确初始化{。}}。

非常感谢任何帮助。

2 个答案:

答案 0 :(得分:1)

在Windows上,wchar_t通常为UTF-16(little-endian)。它们通常不以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个字节)所需的字节数。这样可以避免不安全的类型转换,但除此之外应该如上所述。

我正在做这件事,所以上面的代码就是一个例子&可能不一定有效 - 使用危险: - )

答案 1 :(得分:0)

似乎GeertJohan的库尚未针对最近的cgo更改进行更新,但是fork有,请尝试github.com/vitaminwater/cgo.wchargodoc)。

如果C函数写入C类型,则传递C类型的变量。

一个(狡猾的)例子:

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 世界