Re: WindowsAPI - Problem with DECLARE_HANDLE definition

2013-09-20 Thread Simen Kjaeraas

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

2013-09-19 Thread Kagamin
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

2013-09-19 Thread Kagamin
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

2013-09-19 Thread Andrej Mitrovic
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

2013-09-19 Thread Kagamin
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

2013-09-11 Thread Kagamin

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

2013-09-11 Thread Andrej Mitrovic
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

2013-09-11 Thread Simen Kjaeraas

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

2013-09-08 Thread Stewart Gordon
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

2013-09-08 Thread Mike Parker

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

2013-09-08 Thread Vladimir Panteleev

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

2013-09-08 Thread Vladimir Panteleev

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.