【问题标题】:COM out-ptr remains null in clientCOM out-ptr 在客户端中保持为空
【发布时间】:2016-11-29 20:07:16
【问题描述】:

什么会导致IEnumString->Next() 调用调用正确的函数但将客户端的指针保留为空?一切都是 64 位(Windows 10)。

数据流:我的 DLL -> MSSpellCheckingHost -> 客户端

In my code (Github link) 一切都检查完毕。分配和复制看起来不错。但是客户端看到一个空指针,但只有当通过ISpellCheckProvider->Suggest(); 来时它才能通过ISpellCheckProviderFactory->get_SupportedLanguages() 正常工作

来自EnumString.hpp 的片段:

template<typename String>
inline void CoCopyWString(const String& in, PWSTR* out) {
    debugp p(__FUNCTION__);
    p(in, static_cast<void*>(*out));
    *out = reinterpret_cast<LPWSTR>(CoTaskMemAlloc(sizeof(wchar_t)*(in.size() + 1)));
    std::copy(in.begin(), in.end(), *out);
    (*out)[in.size()] = 0;
    p(std::wstring(*out), static_cast<void*>(*out));
}

class EnumString : public IEnumString {
public:
...
    IFACEMETHODIMP Next(ULONG celt, LPOLESTR *rgelt, ULONG *pceltFetched) {
        debugp p(__FUNCTION__);
        p(celt);
        HRESULT hr = S_FALSE;

        ULONG i = 0;
        for (; i < celt && current < strings.size(); ++i, ++current) {
            p(i, current);
            CoCopyWString(strings[current], rgelt+i);
            p(static_cast<void*>(rgelt + i), static_cast<void*>(rgelt[i]));
        }

        if (celt > 1) {
            *pceltFetched = i;
        }
        if (i == celt) {
            hr = S_OK;
        }

        return hr;
    }
...
private:
    std::vector<std::wstring> strings;
    ULONG current = 0;
};

如图所示,有很多调试打印,因为将调试器附加到 MSSpellCheckingHost 非常烦人,它们会产生预期的输出,例如:

EnumString::Next
    1
    0 0
    CoCopyWString
        i-llu 0000000000000000
        i-llu 000001CC35682AE0
    ~CoCopyWString
    000001CC356A1F50 000001CC35682AE0
~EnumString::Next

...显示输出指针被设置并且指向的数据是正确的。它在调用SupportedLanguages 时起作用-将正确的值返回给枚举器并使用该值,因此它不能为空。但是当使用Suggest() 时,结果并没有通过。

返回通过CoTaskMemAlloc 分配的结构的所有其他函数也可以工作,因此总体而言,主机看起来可以正常工作,除了那一种情况。

【问题讨论】:

  • “让客户的指针为空”是什么意思?客户端应该传递一个指向指针数组的指针,该数组由Next 填充。这就是客户端代码的作用吗?
  • @Cheersandhth.-Alf,是的,客户是 MS 自己的样本。它传递了正确的东西(归结为 wchar_t**),但是当Next 返回时它仍然为空。我什至无法调试路径,因为 MSSpellCheckingHost 没有可用的调试符号。我确实尝试在输出中设置任何位,只是为了看看我是否可以摆弄它,但在那一次调用中没有任何结果。
  • 您必须始终分配*pceltFetched。 0 是“没有建议”的正确值。
  • @HansPassant,你是对的。我阅读文档说pceltFetched 仅在celt &gt; 1 时使用,但实际上是在celt &gt; 1 || pceltFetched 时使用。我永远不会抓住那个。发布为真正的答案...
  • 好吧,检查它是否修复了错误。一旦你得到确认,你可以尽可能地发布答案。

标签: c++ windows com


【解决方案1】:

正如 Hans Passant 指出的,sn-p

    if (celt > 1) {
        *pceltFetched = i;
    }

应该是

    if (pceltFetched) {
        *pceltFetched = i;
    }

【讨论】:

    猜你喜欢
    • 2017-05-30
    • 1970-01-01
    • 2015-01-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多