为什么我可以调用StringFromCLSID,即使没有调用CoInitializeEx之前
Why I can call StringFromCLSID even without the calling of CoInitializeEx before?
我正在通过c++学习COM。从MSDN:
应用程序需要在创建CoInitializeEx之前使用它其他COM库调用,内存分配函数除外。
内存分配函数我认为是CoTaskMemAlloc
和CoTaskMemFree
。
但是我看到,我的"Hello World"在没有CoInitializeEx
和CoUninitialize
函数调用的情况下工作得很好。在我的代码中,我使用StringFromCLSID
函数,该函数在combaseapi.h
头中声明。所以,在我看来是一个COM函数。我的代码:
/* entry_point.cpp */
#include "Tools.h"
#include <objbase.h>
int main(){
HRESULT hr = ::CoInitializeEx(nullptr, COINIT_MULTITHREADED);
if (FAILED(hr)){
trace("Can't initialize COM for using in the current thread.");
keep_window_opened();
return 1;
}
// {D434CF7D-2CDD-457A-A4EF-5822D629CE83}
static const CLSID clsid =
{ 0xd434cf7d, 0x2cdd, 0x457a, {
0xa4, 0xef, 0x58, 0x22, 0xd6, 0x29, 0xce, 0x83 } };
const size_t SIZE = 39;
wchar_t* wch = nullptr;
hr = ::StringFromCLSID(clsid, &wch);
if (FAILED(hr)){
trace("Can't convert CLSID to wchar_t array.");
}
else{
trace("CLSID converted to wchar_t array.");
char mch[SIZE];
size_t count = 0;
int result = ::wcstombs_s(&count, mch, wch, SIZE);
if (result){
trace("Can't convert wchar_t array to char array.");
}
else{
trace(mch);
}
::CoTaskMemFree(wch);
}
::CoUninitialize();
keep_window_opened();
return 0;
}
如果我删除CoInitializeEx
和CoUninitialize
函数的调用,那么我的代码仍然工作。我预料它不会成功……
为什么StringFromCLSID
在没有调用CoInitializeEx
的情况下也能工作?
谢谢。
StringFromCLSID
基本上是将GUID值(字节)打印成字符串,然后使用连字符和大括号对其进行格式化。不涉及其他任何内容,因此,要使此调用成功,实际上不需要初始化COM。
您必须执行CoInitialize
/CoInitializeEx
以确保安全,但不这样做您不一定会立即遇到问题。
为什么StringFromCLSID工作,甚至没有调用CoInitializeEx之前?
关键信息在文档中有详细说明。
CoInitializeEx
功能:
在调用任何库函数之前,您需要在线程上初始化COM库,除了…内存分配函数。否则,COM函数将返回coe_notinitialized。
StringFromCLSID
功能:
StringFromCLSID调用StringFromGUID2函数将全局唯一标识符(GUID)转换为可打印字符的字符串。
调用者负责通过调用CoTaskMemFree函数释放分配给字符串的内存。
StringFromCLSID()
返回一个动态分配的字符串。我们可以从上面突出显示的句子中推断,内存是使用CoTaskMemAlloc()
分配的——这在文档中被明确地描述为不需要CoInitializeEx()
。
StringFromGUID2()
将GUID
数据格式化到调用者指定的内存块中。格式化字符串不需要COM功能。wsprintfW()
、StringCbPrintfW()
或其他等效函数就足够了。因此,StringFromGUID2()
不需要CoInitializeEx()
,即使没有明确的文档说明。我认为微软不使用他们众多可用的字符串格式化函数之一来实现StringFromGUID2()
是相当短视的。所以我认为可以肯定地说,CoInitializeEx()
不是这方面的要求(除非微软另有说明)。
GUID
结构体只包含一些数字和字节。声明和使用 GUID
不依赖于COM库。你可以在你的代码中自由地使用GUID
,而不需要接触COM——除非你想生成一个新的GUID
,在这种情况下,CoInitializeEx()
对CoCreateGUID()
的要求是模糊的,因为CoCreateGUID()
在COM库中,但被明确地记录为简单地调用UuidCreate()
,而不是在RPC库中。
所以这就是为什么你可以先调用StringFromCLSID()
而不调用CoInitializeEx()
。GUID
本身不需要COM初始化。字符串被分配了一个不需要COM初始化的内存函数。字符串的格式化方式使得很可能不需要COM初始化。
- 什么时候调用组成单元对象的析构函数
- 对RValue对象调用的LValue ref限定成员函数
- 为什么使用 "this" 指针调用派生成员函数?
- 函数调用中参数的顺序重要吗
- OpenGL - 在抛出"__gnu_cxx::recursive_init_error"实例后终止调用?
- 基于另一个成员参数将函数调用从类传递给它的一个成员
- 为什么我的C#代码在调用回C++COM直到Task时会暂停.等待/线程.加入
- 在c++类上调用void函数
- 为什么 std::unique 不调用 std::sort?
- 调用专用模板时出错"no matching function for call to [...]"
- 选择要调用的构造函数
- C++为什么尽管我调用了void函数,它却不起作用
- 构造函数正在调用一个使用当前类类型的函数
- 变量没有改变?通过向量的函数调用
- 没有为自己的结构调用列表推回方法
- 何时调用 Windows 控制台应用程序需要 CoInitialize
- 从 BackgroundWorker C# 调用的 CoInitialize
- CoInitialize 尚未被调用 - (从 DirectXTK 加载 gamepad.h,无需库)
- 我需要在C++ REST SDK中调用CoInitialize
- 无论如何,在初始化列表之前调用CoInitialize()