为什么我可以在没有调用 CoInitializeEx 的情况下调用 StringFromCLSID?
Why I can call StringFromCLSID even without the calling of CoInitializeEx before?
我正在通过 C++ 学习 COM。来自 MSDN:
Applications are required to use CoInitializeEx before they make any
other COM library calls except for memory allocation functions.
内存分配函数在我看来是CoTaskMemAlloc
和CoTaskMemFree
。
但我明白了,无论是否调用 CoInitializeEx
和 CoUninitialize
函数,我的 "Hello World" 都可以正常工作。在我的代码中,我使用了在 combaseapi.h
header 中声明的 StringFromCLSID
函数。所以,我认为它是一个 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
,但不这样做不一定会立即遇到问题。
Why StringFromCLSID work even without the calling of CoInitializeEx before?
文档中说明了关键信息。
You need to initialize the COM library on a thread before you call any of the library functions except ... the memory allocation functions. Otherwise, the COM function will return CO_E_NOTINITIALIZED.
StringFromCLSID calls the StringFromGUID2 function to convert a globally unique identifier (GUID) into a string of printable characters.
The caller is responsible for freeing the memory allocated for the string by calling the CoTaskMemFree function.
StringFromCLSID()
returns a dynamically allocated string. We can infer from the highlighted sentence above that the memory is allocated using CoTaskMemAlloc()
- which is explicitly documentated as not requiring CoInitializeEx()
.
StringFromGUID2()
formats GUID
data into a caller-specified memory block. Formatting a string does not require COM functionality. The wsprintfW()
, StringCbPrintfW()
, or other equivalent function would suffice. So CoInitializeEx()
should not be required for StringFromGUID2()
, even though this is not explicitly documented. I think it would be pretty short-sighted for Microsoft to not use one of their many available string formatting functions to implement StringFromGUID2()
. So I think it should be safe to say that CoInitializeEx()
不是此要求(除非 Microsoft 另有说明)。
GUID
structure simply contains a few numbers and bytes. Declaring and using a GUID
is not dependent on the COM library. You can freely use a GUID
in your code all you want without touching COM at all - unless you want to generate a new GUID
, in which case the CoInitializeEx()
requirement for CoCreateGUID()
is blurry as CoCreateGUID()
is in the COM library but is explicitly documented as simply calling UuidCreate()
,它在 RPC 库中。
所以这就是为什么你可以调用 StringFromCLSID()
without calling CoInitializeEx()
first. A GUID
本身不需要 COM 初始化。正在为字符串分配不需要 COM 初始化的内存函数。字符串的格式设置很可能不需要 COM 初始化。
我正在通过 C++ 学习 COM。来自 MSDN:
Applications are required to use CoInitializeEx before they make any other COM library calls except for memory allocation functions.
内存分配函数在我看来是CoTaskMemAlloc
和CoTaskMemFree
。
但我明白了,无论是否调用 CoInitializeEx
和 CoUninitialize
函数,我的 "Hello World" 都可以正常工作。在我的代码中,我使用了在 combaseapi.h
header 中声明的 StringFromCLSID
函数。所以,我认为它是一个 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
,但不这样做不一定会立即遇到问题。
Why StringFromCLSID work even without the calling of CoInitializeEx before?
文档中说明了关键信息。
You need to initialize the COM library on a thread before you call any of the library functions except ... the memory allocation functions. Otherwise, the COM function will return CO_E_NOTINITIALIZED.
StringFromCLSID calls the StringFromGUID2 function to convert a globally unique identifier (GUID) into a string of printable characters.
The caller is responsible for freeing the memory allocated for the string by calling the CoTaskMemFree function.
StringFromCLSID()
returns a dynamically allocated string. We can infer from the highlighted sentence above that the memory is allocated using CoTaskMemAlloc()
- which is explicitly documentated as not requiring CoInitializeEx()
.
StringFromGUID2()
formats GUID
data into a caller-specified memory block. Formatting a string does not require COM functionality. The wsprintfW()
, StringCbPrintfW()
, or other equivalent function would suffice. So CoInitializeEx()
should not be required for StringFromGUID2()
, even though this is not explicitly documented. I think it would be pretty short-sighted for Microsoft to not use one of their many available string formatting functions to implement StringFromGUID2()
. So I think it should be safe to say that CoInitializeEx()
不是此要求(除非 Microsoft 另有说明)。
GUID
structure simply contains a few numbers and bytes. Declaring and using a GUID
is not dependent on the COM library. You can freely use a GUID
in your code all you want without touching COM at all - unless you want to generate a new GUID
, in which case the CoInitializeEx()
requirement for CoCreateGUID()
is blurry as CoCreateGUID()
is in the COM library but is explicitly documented as simply calling UuidCreate()
,它在 RPC 库中。
所以这就是为什么你可以调用 StringFromCLSID()
without calling CoInitializeEx()
first. A GUID
本身不需要 COM 初始化。正在为字符串分配不需要 COM 初始化的内存函数。字符串的格式设置很可能不需要 COM 初始化。