gpt4 book ai didi

go - COM 中的 UTF-16 字符串

转载 作者:行者123 更新时间:2023-12-01 22:15:57 27 4
gpt4 key购买 nike

请有人解释一下 Go 指针的魔法
我尝试调用 COM 函数

func (p *IServer) Authorize(user, pass string) error {
UserName := ole.SysAllocString(login.UserName)
defer ole.SysFreeString(UserName)
UserPsw := ole.SysAllocString(login.UserPsw)
defer ole.SysFreeString(UserPsw)

// HRESULT IServer::Authorize([in] BSTR UserName, [in] BSTR UserPsw, [out] VARIANT* SID, [out, retval] long* Result)
hr, _, _ := Call(p.VTable().Authorize,
uintptr(unsafe.Pointer(p)),
uintptr(unsafe.Pointer(UserName)),
uintptr(unsafe.Pointer(UserPsw)),
uintptr(unsafe.Pointer(sid)),
uintptr(unsafe.Pointer(&res)))

...
}

此代码运行良好,但是当我将转换替换为
UserName := syscall.StringToUTF16Ptr(login.UserName)
UserPsw := syscall.StringToUTF16Ptr(login.UserPsw)

它会导致访问违规!来自 go-ole
func SysAllocString(v string) (ss *int16) {
pss, _, _ := procSysAllocString.Call(uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(v))))
ss = (*int16)(unsafe.Pointer(pss))
return
}

我究竟做错了什么?

更新:在 C/C++ 中 wchar* 指针在 386/amd64 中都可以正常工作
void Authorize(IServer* p wchar* user, wchar* pass) {
p.Authorize(user, pass ....
}

最佳答案

SysAllocString 返回 BSTR 类型,com 类型对象。

 typedef struct {
#ifdef _WIN64
DWORD pad;
#endif
DWORD size;
union {
char ptr[1];
WCHAR str[1];
DWORD dwptr[1];
} u; // take it as a starting point of the string
} bstr_t;

换句话说,它是相同的 utf16 编码字符串,但前缀是其大小(Unicode 字符的长度乘以 wchar_t 的大小(2-4 字节))。出于优化的原因,它也有填充。

由于它的 float 大小,最好使用 ole 包而不是重新发明轮子。如果你想自己实现它,并且 wchar_t 的大小为 int16(2 字节),那么你必须执行以下操作:

(半伪代码,我没测试过)

type BSTR *uint16

func SysAllocString(str string) (result BSTR) {
// DWORD == int32 == rune
const padf = "\x00" // only for 64 bit system
const sizef = "\x00"

// int32 == 4 byte
// int16 == 2 byte
const wordSize = unsafe.Sizeof(int16(0))

utf16 := utf16.Encode([]rune(padf + sizef + str))

/* pad is on index 0 and 1 */
size := &utf16[2 /* 0 for 32 bit system */]

// set "size" field as unicode charachers length multypled by size of wchar_t
*(*rune)(unsafe.Pointer(size)) = rune((len(utf16)-2) * int(wordSize))


result = BSTR(&utf16[0])

return
}

// ...
bstr := SysAllocString(login.UserName)

uintptr(unsafe.Pointer(bstr))

关于go - COM 中的 UTF-16 字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60226011/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com