首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >COM中的UTF-16字符串

COM中的UTF-16字符串
EN

Stack Overflow用户
提问于 2020-02-14 20:04:39
回答 1查看 76关注 0票数 0

谁来解释一下Go指针的魔力我试着调用COM函数

代码语言:javascript
复制
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)))

   ...
}

这段代码运行良好,但当我将转换替换为

代码语言:javascript
复制
UserName := syscall.StringToUTF16Ptr(login.UserName)
UserPsw := syscall.StringToUTF16Ptr(login.UserPsw)

它会导致访问冲突!来源: go-ole

代码语言:javascript
复制
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中都能正常工作

代码语言:javascript
复制
void Authorize(IServer* p wchar* user, wchar* pass) {
   p.Authorize(user, pass ....
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-02-15 04:35:41

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

代码语言:javascript
复制
 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字节))。出于优化的原因,它也有填充。

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

(半个伪代码,我没有测试它)

代码语言:javascript
复制
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))
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/60226011

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档