Re: WindowsAPI - Problem with DECLARE_HANDLE definition
On 2013-09-19, 10:06, Kagamin wrote: On Wednesday, 11 September 2013 at 20:20:13 UTC, Simen Kjaeraas wrote: On 2013-09-11, 20:29, Andrej Mitrovic wrote: On 9/11/13, Kagamin s...@here.lot wrote: I'd say, strong handles shouldn't act as pointers (and shouldn't contain pointers), so null shouldn't work. NULL is already used in a ton of WinAPI C/C++ code and MSDN documentation, it would be a major pain in the ass to have to use e.g. HWND(0) instead. How's about enum NULL = HANDLE(0); Honestly I hate that, and am convinced the correct way to fix this is for D to add opImplicitCastFrom. Or multiple alias this: struct _NULL { HANDLE zero; void* ptr; alias zero this; alias ptr this; } If you want opaque handles, that does not solve the problem. What would solve the problem is something like this: struct DECLARE_HANDLE(int line = __LINE__, string file = __FILE__T) { private void* payload; private this(void* value) { payload = value; } ref DECLARE_HANDLE opAssign(typeof(null) value) { payload = null; return this; } DECLARE_HANDLE opImplicitCastFrom(typeof(null) value) { return DECLARE_HANDLE(null); } } alias DECLARE_HANDLE!(__LINE__, __FILE__) HANDLE; // BUG11074 alias DECLARE_HANDLE!(__LINE__, __FILE__) HWND; // BUG11074 void test() { void* voidPointer; HANDLE handle; HWND window; SomeWindowsFunctionTakingAHandle(null); // No problem! SomeWindowsFunctionTakingAHandle(handle); // No problem! SomeWindowsFunctionTakingAHandle(voidPointer); // Does not compile. SomeWindowsFunctionTakingAHandle(window); // Does not compile. } -- Simen
Re: WindowsAPI - Problem with DECLARE_HANDLE definition
On Wednesday, 11 September 2013 at 18:29:09 UTC, Andrej Mitrovic wrote: On 9/11/13, Kagamin s...@here.lot wrote: I'd say, strong handles shouldn't act as pointers (and shouldn't contain pointers), so null shouldn't work. NULL is already used in a ton of WinAPI C/C++ code and MSDN documentation, it would be a major pain in the ass to have to use e.g. HWND(0) instead. In my experience writing a winapi call already takes some effort and specifying HANDLE(0) instead of NULL doesn't add any comparable difficulty.
Re: WindowsAPI - Problem with DECLARE_HANDLE definition
On Wednesday, 11 September 2013 at 20:20:13 UTC, Simen Kjaeraas wrote: On 2013-09-11, 20:29, Andrej Mitrovic wrote: On 9/11/13, Kagamin s...@here.lot wrote: I'd say, strong handles shouldn't act as pointers (and shouldn't contain pointers), so null shouldn't work. NULL is already used in a ton of WinAPI C/C++ code and MSDN documentation, it would be a major pain in the ass to have to use e.g. HWND(0) instead. How's about enum NULL = HANDLE(0); Honestly I hate that, and am convinced the correct way to fix this is for D to add opImplicitCastFrom. Or multiple alias this: struct _NULL { HANDLE zero; void* ptr; alias zero this; alias ptr this; }
Re: WindowsAPI - Problem with DECLARE_HANDLE definition
On 9/19/13, Kagamin s...@here.lot wrote: In my experience writing a winapi call already takes some effort and specifying HANDLE(0) instead of NULL doesn't add any comparable difficulty. It adds difficulty in having to fix existing code that will be broken.
Re: WindowsAPI - Problem with DECLARE_HANDLE definition
I don't think strong handles are backwards compatible: legacy code may as well rely on HANLDE being void* or compatible with each other - exactly what strong handles break.
Re: WindowsAPI - Problem with DECLARE_HANDLE definition
On Sunday, 8 September 2013 at 23:52:46 UTC, Stewart Gordon wrote: The problem is that null no longer works. How to fix? I'd say, strong handles shouldn't act as pointers (and shouldn't contain pointers), so null shouldn't work, I use HANDLE(0) instead of null. Use void* for maximum compatibility (weak handles).
Re: WindowsAPI - Problem with DECLARE_HANDLE definition
On 9/11/13, Kagamin s...@here.lot wrote: I'd say, strong handles shouldn't act as pointers (and shouldn't contain pointers), so null shouldn't work. NULL is already used in a ton of WinAPI C/C++ code and MSDN documentation, it would be a major pain in the ass to have to use e.g. HWND(0) instead.
Re: WindowsAPI - Problem with DECLARE_HANDLE definition
On 2013-09-11, 20:29, Andrej Mitrovic wrote: On 9/11/13, Kagamin s...@here.lot wrote: I'd say, strong handles shouldn't act as pointers (and shouldn't contain pointers), so null shouldn't work. NULL is already used in a ton of WinAPI C/C++ code and MSDN documentation, it would be a major pain in the ass to have to use e.g. HWND(0) instead. How's about enum NULL = HANDLE(0); Honestly I hate that, and am convinced the correct way to fix this is for D to add opImplicitCastFrom. -- Simen
WindowsAPI - Problem with DECLARE_HANDLE definition
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.
Re: WindowsAPI - Problem with DECLARE_HANDLE definition
On 9/9/2013 8:52 AM, Stewart Gordon wrote: What do people think we should do? Eliminate declare handle and alias all HANDLE types to void*.
Re: WindowsAPI - Problem with DECLARE_HANDLE definition
On Sunday, 8 September 2013 at 23:52:46 UTC, Stewart Gordon wrote: 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. This is a showstopper. It breaks existing code in subtle ways. 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? This is fine as far as the GC goes. Error messages are not great, though: cannot implicitly convert expression (h) of type const(HANDLE_)* to const(HWND_)*. Not sure about object code - one possibility would be to fix DMD to support class declarations (e.g. class HWND_ : HANDLE_; with no body). 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. This is not much better than writing HWND.init (which is how I've been working around the issues). 4. Abandon this hierarchy idea and just define DECLARE_HANDLE the same way as the MinGW C headers do. Supporting the functionality of the STRICT define would be a good start; I don't think that involves any hierarchies. I think an important goal is to avoid breaking most correct code and maximize compatibility with C code, so using a special literal for null is out. By the way, another problem with the current implementation is casts. At the moment, they can get quite verbose, and confusing to implement (one needs to look up the hierarchy of the handle types). For example, calling LocalFree with a LPCWSTR as when using FormatMessage now looks like this: LocalFree(HLOCAL(HANDLE(lpMsgBuf))); Having the handle types be some kind of pointer would allow using a more conventional casting syntax.
Re: WindowsAPI - Problem with DECLARE_HANDLE definition
On Monday, 9 September 2013 at 01:25:00 UTC, Mike Parker wrote: On 9/9/2013 8:52 AM, Stewart Gordon wrote: What do people think we should do? Eliminate declare handle and alias all HANDLE types to void*. I think this is the lazy and shortsighted answer. Even the official Windows headers have a strict typing mode (the STRICT define), which is recommended for new applications: http://msdn.microsoft.com/en-us/library/windows/desktop/aa383731(v=vs.85).aspx Most code would benefit from additional compile-time checks, as the number of places where a cast is required is small. Stewart is attempting to reduce this number even further by defining a handle type hierarchy, something which isn't possible in C but might be possible in D.