WindowsAPI - Problem with DECLARE_HANDLE definition

Stewart Gordon smjg_1998 at yahoo.com
Sun Sep 8 16:52:43 PDT 2013


It has just come to my attention that there's a problem with the DECLARE_HANDLE template 
in the Win32 bindings.

This is the definition in MinGW:

     #define DECLARE_HANDLE(n) typedef struct n##__{int i;}*n

And this is the definition in our bindings:

     package template DECLARE_HANDLE(string name, base = HANDLE) {
         mixin ("struct " ~ name ~ " {
             " ~ base.stringof ~ " h;
             alias h this;
         }");
     }

which when mixed in becomes something like

     struct HWND {
         HANDLE h;
         alias h this;
     }

The idea behind this was to effectively create a taxonomy of handle types, each implicitly 
convertible to handle types higher up the chain.  This was straightforward when we had 
typedefs.

The problem is that null no longer works.  How to fix?  Ideas that come to mind:


1. Define a hierarchy of dummy classes for the handle types.  No actual objects will exist 
of these types, but since classes are reference types they can be set to null.

But there's a nasty bug lurking in this: if somebody tries to compare handles using ==, it 
will dereference the pointer, and look in vain for the vtable and the opEquals method 
defined therewithin ... cue major chaos.


2. Do 1, but use pointers to these classes as the handle types.

     class HANDLE_ {}
     alias const(HANDLE_)* HANDLE;
     class HWND_ : HANDLE_ {}
     alias const(HWND_)* HWND;

This would avoid the dereferencing behaviour.  It's to be hoped that all Windows 
programmers know that, although handles are declared as pointer types, they cannot 
meaningfully be dereferenced.  But what would the GC do, especially given that there are 
two levels of indirection neither of which points to an appropriate memory location?

Moreover, will defining classes in the bindings cause object code to be generated for 
them, which the program will later rely on in order to link?  This is something I am 
trying to get rid of completely.


3. Keep the current implementation, but implement an enum member NULL in each handle type, 
like this:

     struct HWND {
         HANDLE h;
         alias h this;
         enum HWND NULL = cast(HWND) 0;
     }

Programmers still can't use null, but writing HWND.NULL might be acceptable as the next 
best thing.


4. Abandon this hierarchy idea and just define DECLARE_HANDLE the same way as the MinGW C 
headers do.


What do people think we should do?

Stewart.

-- 
My email address is valid but not my primary mailbox and not checked regularly.  Please 
keep replies on the 'group where everybody may benefit.


More information about the Digitalmars-d mailing list