COM 输出指针在客户端中保持为空
COM out-ptr remains null in client
什么会导致 IEnumString->Next() 调用调用正确的函数但使客户端指针为空?一切都是 64 位 (Windows 10).
数据流:我的DLL -> MSSpellCheckingHost -> 客户端
In my code (Github link) everything checks out. The allocation and copy look fine. But the client sees a null pointer, but only when coming via ISpellCheckProvider->Suggest(); it works fine via 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 is called - that returns the correct value to the enumerator and the value is used so it couldn't have been null. But when Suggest()时有效,结果没有通过。
通过 CoTaskMemAlloc
分配的 return 结构的所有其他功能也可以使用,因此主机总体上看起来是可用的,除了那个情况。
正如 Hans Passant 指出的那样,该片段
if (celt > 1) {
*pceltFetched = i;
}
应该是
if (pceltFetched) {
*pceltFetched = i;
}
什么会导致 IEnumString->Next() 调用调用正确的函数但使客户端指针为空?一切都是 64 位 (Windows 10).
数据流:我的DLL -> MSSpellCheckingHost -> 客户端
In my code (Github link) everything checks out. The allocation and copy look fine. But the client sees a null pointer, but only when coming via ISpellCheckProvider->Suggest(); it works fine via 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 is called - that returns the correct value to the enumerator and the value is used so it couldn't have been null. But when Suggest()时有效,结果没有通过。
通过 CoTaskMemAlloc
分配的 return 结构的所有其他功能也可以使用,因此主机总体上看起来是可用的,除了那个情况。
正如 Hans Passant 指出的那样,该片段
if (celt > 1) {
*pceltFetched = i;
}
应该是
if (pceltFetched) {
*pceltFetched = i;
}