views:

448

answers:

4

I'm writing a Windows console application in C++ and would like to return zero on success and a meaningful error code on failure (i.e., S_OK should return 0, and E_OUTOFMEMORY should return a different return value than E_FAIL and so on). Is the following an okay approach?:

int wmain(int argc, wchar_t *argv[])
{
    HRESULT hr = DoSomething();
    return (int) hr;
}

Or is there a better way? Maybe a standard Win32 API function or macro that I'm forgetting or failing to find?

+3  A: 

HRESULT is just a 32-bit integer, with each code being a different value, so what you are doing is what you want.

Steve Gilham
If what he wants is for success to sometimes be represented by a non-zero value (S_FALSE?). But he did say he wants to return zero on success.
Paul Mitchell
+1  A: 

The "better way" is to use a C++ style cast:

HRESULT hr = DoSomething();
return static_cast<int>(hr);

Otherwise, like Steve said, it's just an integer. It is defined as a long, not an int, but instead of casting from HRESULT to long to int, you can obviously just do it in one maneuver.

(That is to say, windows.h makes the assumption that long will be a 32-bit integer, which the C & C++ standard's do not guarantee. But that's just how things go, I suppose.)


Even better is that this does not require a cast at all.

GMan
As a matter of fact, since HRESULT is just a typedef for 'long' you don't even need a cast at all.
Michael Burr
Hm, funny what happens when you stop looking at the big picture.
GMan
+1  A: 

There is an implicit conversion, so the cast is unnecessary.

(Rather more unfortunately, there is also an implicit conversion to bool, and to the Win32 BOOL typedef, so S_OK converts to false and all other values (including errors) convert to true - a common source of errors in COM programs.)

Daniel Earwicker
+2  A: 

The OP wants a return value of zero to indicate success. There are success codes which are non-zero and so...

if ( SUCCEEDED( hr ) )
    return 0;
return hr;
Paul Mitchell
+1 it is not enough assuming S_OK == 0, SUCCEEDED( ) should be used.
Anders K.
Good catch. Voted up. Still, in this case, I think I want to return a different value for S_FALSE and the like.
Brian