我需要在非托管 Windows C++ 项目中创建一个
GUID
。 我习惯了 C#,我会使用 Guid.NewGuid()
。 (非托管 Windows)C++ 版本是什么?
UuidCreate() 具有完全相同的效果。但是,您需要传递将接收生成值的变量的地址:
UUID newId;
UuidCreate( &newId );
我相信 Guid.NewGuid() 只是在 .NET 运行时中映射到它。
以下是获取生成的 GUID 的结果字符串值的代码片段:
// For UUID
#include <Rpc.h>
#pragma comment(lib, "Rpcrt4.lib")
int _tmain(int argc, _TCHAR* argv[])
{
// Create a new uuid
UUID uuid;
RPC_STATUS ret_val = ::UuidCreate(&uuid);
if (ret_val == RPC_S_OK)
{
// convert UUID to LPWSTR
WCHAR* wszUuid = NULL;
::UuidToStringW(&uuid, (RPC_WSTR*)&wszUuid);
if (wszUuid != NULL)
{
//TODO: do something with wszUuid
// free up the allocated string
::RpcStringFreeW((RPC_WSTR*)&wszUuid);
wszUuid = NULL;
}
else
{
//TODO: uh oh, couldn't convert the GUID to string (a result of not enough free memory)
}
}
else
{
//TODO: uh oh, couldn't create the GUID, handle this however you need to
}
return 0;
}
API参考:
Guid.NewGuid的文档指出了它是如何实现的:
这是一个方便的 static 方法,您可以调用它来获取新的 Guid。该方法包装了对 Windows CoCreateGuid 函数的调用。
因此
Guid.NewGuid()
的原生等效项是 CoCreateGuid()
。
CoCreateGuid 调用UuidCreate,以生成 GUID。不过,这两个 API 调用略有不同:虽然
UuidCreate
返回一个 UUID,并且保证对于创建它的计算机来说是唯一的,但 CoCreateGuid
生成一个绝对唯一的 GUID。
如果您需要决定使用哪个 API,请参阅文档中的相关部分。
出于安全原因,通常希望防止网络上的以太网地址在公司或组织外部可用。 UuidCreate 函数生成一个 UUID,无法追踪到生成它的计算机的以太网地址。它也不能与同一计算机上创建的其他UUID关联。
CoCreateGuid函数调用RPC函数UuidCreate,它创建一个GUID,一个全局唯一的128位整数。当您需要一个绝对唯一的数字并将其用作分布式环境中的持久标识符时,请使用CoCreateGuid。
#include <string>
#include <sstream>
#include <iostream>
#include <windows.h>
#include <iomanip>
int main()
{
GUID guid;
CoCreateGuid(&guid);
std::ostringstream os;
os << std::hex << std::setw(8) << std::setfill('0') << guid.Data1;
os << '-';
os << std::hex << std::setw(4) << std::setfill('0') << guid.Data2;
os << '-';
os << std::hex << std::setw(4) << std::setfill('0') << guid.Data3;
os << '-';
os << std::hex << std::setw(2) << std::setfill('0') << static_cast<short>(guid.Data4[0]);
os << std::hex << std::setw(2) << std::setfill('0') << static_cast<short>(guid.Data4[1]);
os << '-';
os << std::hex << std::setw(2) << std::setfill('0') << static_cast<short>(guid.Data4[2]);
os << std::hex << std::setw(2) << std::setfill('0') << static_cast<short>(guid.Data4[3]);
os << std::hex << std::setw(2) << std::setfill('0') << static_cast<short>(guid.Data4[4]);
os << std::hex << std::setw(2) << std::setfill('0') << static_cast<short>(guid.Data4[5]);
os << std::hex << std::setw(2) << std::setfill('0') << static_cast<short>(guid.Data4[6]);
os << std::hex << std::setw(2) << std::setfill('0') << static_cast<short>(guid.Data4[7]);
std::string s(os.str());
std::cout << s << std::endl;
}
或者,您可以使用
sprintf_s
进行字符串转换
GUID guid;
CoCreateGuid(&guid);
char guidStr[37];
sprintf_s(
guidStr,
"%08lX-%04hX-%04hX-%02hhX%02hhX-%02hhX%02hhX%02hhX%02hhX%02hhX%02hhX",
guid.Data1, guid.Data2, guid.Data3,
guid.Data4[0], guid.Data4[1], guid.Data4[2], guid.Data4[3],
guid.Data4[4], guid.Data4[5], guid.Data4[6], guid.Data4[7]);
std::string s(guidStr);
#include <Windows.h>
#include <array>
std::string getGUID()
{
std::string result{};
GUID guid;
if (S_OK == CoCreateGuid(&guid))
{
std::array<char, 36> buffer{}; //32 characters of guid + 4 '-' in-between
snprintf(buffer.data(), buffer.size(), "{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
guid.Data1, guid.Data2, guid.Data3, guid.Data4[0], guid.Data4[1], guid.Data4[2], guid.Data4[3], guid.Data4[4], guid.Data4[5], guid.Data4[6], guid.Data4[7]);
result = std::string(buffer.data());
}
return result;
}
winrt::Windows::Foundation::GuidHelper::CreateNewGuid()
它返回
winrt::guid
类型的结构。您稍后可以将其传递给
winrt::to_hstring
来获取
winrt::hstring
类型的结构体,然后将其传递给
winrt::to_string
来获取
std::string
类型。
CoCreateGUID
中
combase.dll
的实现所做的就是调用
UuidCreate
,如果结果是
RPC_S_UUID_LOCAL_ONLY
,则将其替换为
S_OK
:
#include <rpc.h>
#pragma comment(lib, "rpcrt4.lib")
static const int uuid_string_length = 36;
HRESULT CreateGUID(std::string& GUID)
{
UUID uuid = { 0 };
RPC_CSTR uuid_string = nullptr;
HRESULT hr = UuidCreate(&uuid);
hr = (hr == RPC_S_UUID_LOCAL_ONLY) ? S_OK : hr;
if (SUCCEEDED(hr)) {
hr = UuidToStringA(&uuid, &uuid_string);
}
if (SUCCEEDED(hr)) {
GUID.resize(uuid_string_length);
memcpy(&GUID[0], uuid_string, uuid_string_length);
}
if (uuid_string != nullptr) {
RpcStringFreeA(&uuid_string);
}
return hr;
}
这是正确的做法,因为 GUID 不如 UUID 唯一。