views:

77

answers:

2

Windows SDK features IsEqualGUID() function and operator==() for two GUIDs that return BOOL (equivalent to int):

// Guiddef.h
#ifdef __cplusplus
__inline int IsEqualGUID(REFGUID rguid1, REFGUID rguid2)
{
    return !memcmp(&rguid1, &rguid2, sizeof(GUID));
}
#else   // ! __cplusplus
    #define IsEqualGUID(rguid1, rguid2) (!memcmp(rguid1, rguid2, sizeof(GUID)))
#endif
//also in Guiidef.h
#ifdef __cplusplus
__inline int operator==(REFGUID guidOne, REFGUID guidOther)
{
    return IsEqualGUID(guidOne,guidOther);
}
#endif

What's the point in that int? I understand that C doesn't have bool datatype, but there's an #ifdef __cplusplus around, so this code will only be compiled as C++, so bool will be supported anyway. Having a negation near memcmp() effectively transforms all possible values returned from memcmp() into zero and nonzero.

Also there're no user-defined operators in C - only C++ supports them. So the operator== would not compile in C code anyway.

Are there any reasons for choosing int instead of bool here?

+6  A: 

Because the Windows API exposes IsEqualGUID() as a function returning a BOOL. They need to keep a stable interface. BOOL and bool are different sizes, and the Windows API is designed to be compatible with a variety of languages and compilers. Remember that there are other languages other than C++ that interact with the Windows API.

On C and C++, IsEqualGUID() is implemented in terms of memcmp(), but IsEqualGUID() is also implemented in ole32.dll. You can obtain the function from ole32.dll:

REFGUID guid1 = IID_IUnknown;
REFGUID guid2 = IID_AsyncIUnknown;
typedef BOOL (WINAPI *IsEqualGUIDFuncType)(REFGUID, REFGUID);
HMODULE h = ::LoadLibrary("ole32.dll");
IsEqualGUIDFuncType f = reinterpret_cast<IsEqualGUIDFuncType>
    (::GetProcAddress(h, "IsEqualGUID"));
if(f != NULL)
{
    if(f(guid1, guid2) != 0)
        ::printf("true\n");
    else
        ::printf("false\n");
}
::FreeLibrary(h);

So even though it's implemented as an inline function in C++, other languages may use the DLL implementation of IsEqualGUID(). The C++ version returns a BOOL so it is consistent with the API.

In silico
But that was a "C++" version. Why should C++ interface look like that?
sharptooth
Because the Windows operating system exposes `IsEqualGUID()` as a function returning an `int` (modified my answer to mention this).
In silico
Em... The implementation is right there in the header file. Who then exposes what? How is Windows itself related to it?
sharptooth
It just so happens that it's implemented that way in C++. Remember there are other languages other than C++ that interacts with the Windows API.
In silico
But again... That's not "API" - that's some helper function specific to C++. It doesn't need to be language-independent.
sharptooth
`IsEqualGUID()` is not specific to C++. It can be called from other languages. (like C#: http://www.pinvoke.net/default.aspx/ole32/IsEqualGUID.html)
In silico
I see now. But that doesn't clarify the situation with operator== anyway.
sharptooth
The == operator is probably a convenience for C++ developers. It's present only when `__cplusplus` is defined.
In silico
With this "convenience" each time I want to write `const bool sameIds = guid1 == guid2;` I get C4800 warning and now have to write `const bool sameIds = IsEqualGUID( guid1, guid2 ) != 0;` which is soooo convenient that makes the operator == completely useless.
sharptooth
`const BOOL sameIds = guid1 == guid2;` works without warning. So does `const bool sameIds = (guid1 == guid2) !=0;`. It returns a `BOOL` probably because they want to keep the interface consistent.
In silico
Also, Windows doesn't expose it as a function. In C, you can't take its address., and you can't get it via `GetProcAddress()` either.
MSalters
It is most definitely exposed as a function in `ole32.dll` in which you can get via `GetProcAddress(h, "IsEqualGUID")` after loading `ole32.dll` via `HMODULE h = LoadLibrary("ole32.dll")`.
In silico
+1  A: 

Are there any reasons for choosing int instead of bool here?

There may be more than one reason:

  • consistency of the interface between C and C++ may be desired by the designers

  • backwards compatibility: The Windows SDK has been kept (roughly) backwards compatible since the big bang (or immediately afterwards). This ensures that client code will require less effort to port to a new Windows version and that new Windows versions will have more of an applications base when released (old applications that keep working on new Windows with minimal effort).

  • using only C language types may be desired for interoperability with C

  • the boolean type may not be supported on some platforms - like Windows CE development (I'm not sure if this is actually the case).

utnapistim