Need to access Win32 BOOL as a signed integer

I suppose that we could expose the underlying storage, but is this common enough to warrant that? Is it something that we might want to consider for both DarwinBoolean and WindowsBool?

I don't think Apple's ever made an API for Boolean that returns an out-of-range value, or if they have it got removed with the rest of Carbon. BOOL can't have this problem because it's a true bool on arm64.

2 Likes

I think making GetMessage throwing is definitely the wrong approach. A huge number (possibly the majority) of BOOL Win32 functions actually use the return value to indicate success or failure (but 0 usually means failure, not -1). Reading the docs for each of these functions and deciding which ones should be throwing and which shouldn't would be a big undertaking and, again, Windows API additions and changes in the future are inevitable. And if you only do it for one or two functions, that adds some confusing inconsistency to the API.

An enum also seems like the wrong solution. I can't stress this enough: Win32's a big, weird, largely legacy API that doesn't have the highest quality documentation. It's full of inconsistencies and falls far short of Apple's API's in regards to design and planning. We're never gonna find all its quirks and adding one-off shims just adds to the inconsistency. Not only will users have to keep in-mind the inconsistencies of the original API; they'll have to consider the inconsistencies Swift introduces. For this reason I think it's best to come up with some broad mapping rules that work for the entire API in an automated fashion and stick to those rules.

Adding an intValue property to WindowsBool is something I think should happen regardless of the solution to the return type problem. It allows for users to deal with unforseen use-cases and doesn't get in the way at all in the common case.

As for the return type problem: the bridging peephole sounds like the best solution to me now that I know it exists (thanks @michelf abd @John_McCall). Adding as CInt or as WindowsBool).intValue (either sounds good to me) in the rare cases where it's needed is easy and clear and doesn't get in the way in the common case. And it's consistent with existing practice.

I hesitate to bring this up before the return type problem is resolved, but how's BOOL handled for parameter types? Struct/union member types? Etc.

I agree with @jbatez that there's not really any benefit to standing on ceremony here. We want Win32's BOOL to be imported as Swift.Bool, but since there's evidence that sometimes these types are used non-booleanishly, that's not always going to fly. If we were going to encourage people to use these APIs directly, we might want to come up with some way to make them look good, but the fact is that we probably don't want to encourage that over, say, using some level of wrapping API. Working around the quirks in ad hoc ways in those wrappers is really the most sensible solution.

2 Likes

It should probably work like Objective-C's BOOL: whenever the memory layout matters it uses ObjCBool, otherwise it translates to Bool. So that means it uses ObjCBool in a struct and also when a parameter is passed by address (for an example see FileManager.fileExists). Parameters taking a BOOL by value become a normal Bool.

Although then the question is: is there some cases in the Windows API where a BOOL parameter expects a different value than true or false? I suppose if/when such functions are discovered it would be easy to add an overload in the overlay accepting a CInt. Overloading on parameter type should be less problematic than on return type.

1 Like