【发布时间】: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 > 1时使用,但实际上是在celt > 1 || pceltFetched时使用。我永远不会抓住那个。发布为真正的答案... -
好吧,检查它是否修复了错误。一旦你得到确认,你可以尽可能地发布答案。