How to compare BSTR against a string in c/c++?
wprintf(L"Selecting Audio Input Device: %s\n",
varName.bstrVal);
if(0 == strcmp(varName.bstrVal, "IP Camera [J开发者_运维百科PEG/MJPEG]"))...
The above reports :
error C2664: 'strcmp' : cannot convert parameter 1 from 'BSTR' to 'const char *'
You have to use wcscmp
instead:
if(0 == wcscmp(varName.bstrVal, L"IP Camera [JPEG/MJPEG]"))
{
}
Here is a description of the BSTR data type, it has a length prefix and a real string part which is just an array of WCHAR characters. It also has 2 NULL terminators.
The only thing to look out for is that the BSTR data type can contain embedded NULLs in the string portion, so wcscmp
will only work in the cases where the BSTR does not contain embedded NULLs (which is probably most cases).
As a richer alternative to the C runtime, you could use the Unicode CompareString or CompareStringEx APIs in Win32. If you don't have charset issues to consider, wcscmp is fine though.
My solution:
static const std::wstring IPCamera = L"IP Camera [JPEG/MJPEG]";
if (varName.bstrVal == IPCamera {
//...
All other answers here are either outright wrong or partially incorrect because they are ignoring the fact that both BSTR
and std::wstring
can contain multiple embedded null characters.
That means they should not be compared using wcscmp()
, which will stop comparison on the first \0
it encounters in either string.
Here is how to properly compare BSTR
with std::wstring
:
// Windows.h defines min() and max() as macros
#define NOMINMAX
#include <Windows.h>
#include <string>
// std::string_literals namespace requires C++14,
// but it is needed only to construct strings with
// embedded nulls, not for the comparison itself
using namespace std::string_literals;
int wmain(int argc, wchar_t *argv[])
{
std::wstring String1 = L"I am a happy BSTR \0with \0embedded \0null chars"s;
std::wstring Temp = L"I am a happy bstr \0with \0embedded \0NULL chars"s;
BSTR String2 = SysAllocStringLen(Temp.c_str(), Temp.size());
if (String2 == nullptr) {
return ERROR_OUTOFMEMORY;
}
// make sure not to create a security vulnerability by
// reading past the end of either buffer when comparing
const size_t MaxCount = std::min(String1.size(), static_cast<size_t>(SysStringLen(String2)));
bool Equal = wcsncmp(String1.c_str(), String2, MaxCount) == 0;
if (Equal) {
wprintf(L"Strings are equal\n");
} else {
wprintf(L"Strings are NOT equal\n");
}
SysFreeString(String2);
return 0;
}
Note that the example will print "Strings are NOT equal" unless you change it to use _wcsnicmp()
for case-insensitive comparison.
I always construct _bstr_t
wrappers around BSTRs. It makes things quite a bit easier and more idiomatic:
if(std::string("IP Camera [JPEG/MJPEG]") ==
static_cast<const char*>( _bstr_t(varName.bstrVal) )
{
}
精彩评论