Re: Silent error when using hashmap

2017-07-27 Thread FatalCatharsis via Digitalmars-d

On Thursday, 27 July 2017 at 14:09:37 UTC, Mike Parker wrote:
1. You can't expect exceptions thrown in a callback called from 
C to be propagated through the C side back into the D side. 
That includes errors. It happens on some platforms, but not 
all. On Windows, it does not (at least, not with DMD -- I can't 
speak for LDC).


Figures that the different calling conventions inside the depths 
of windows wouldn't be unwound properly. I'll just make sure to 
do blanket try catches for all throwables in each of these extern 
windows functions so that the buffer flushes for debug output and 
then explicitly exit the program.


You could try to catch the error and stash it for later, but 
better to do change the way you access the map:


```
if(auto pwin = hwnd in winMap) window = *pwin;
```


Knew about this but didn't think you could do this in one line. 
This is fantastic.


3. As I mentioned in another post in this thread, you are doing 
the wrong thing with your window reference. In your call to 
CreateWindowEx, you are correctly casting the reference to 
void*. Everywhere else, you're treating it as a pointer. That's 
wrong! To prove it, you can to this. Declare an instance of 
WinThing at the top of the file.


In CreateWindowEx, you've treated it as such. But then when you 
fetch it out of lpCreateParams, you cast it to a WinThing*. For 
that to be correct, you would have to change CreateWindowEx to 
pass a pointer to the reference (i.e. cast(void*)). But 
actually, that's still not correct because you're taking the 
address of a local variable. So the correct thing to do is to 
leave CreateWindowEx as is, and change all every WinThing* to 
WinThing.


So in the language, references to class objects are treated the 
same syntactically as pointers? So if we were in C++, me 
declaraing a WinThing** (reference to a reference to an object) 
is the same as WinThing* in D? Tried out your changes, that 
definately cleaned up the mess. Why can I not also do the same 
with the create struct like:


CREATESTRUCT createStruct = cast(CREATESTRUCT) lparam;

I take it this is because CREATESTRUCT is not a D class, but a 
struct somewhere?


Note that you don't have to dereference the createStruct 
pointer to access its fields.


Nice tip, didn't realize D implicitly dereferenced pointers when 
you apply the dot operator. Very nice.


There's no reason to make this static member or to call toUTFz 
when you use it. You can use a manifest constant with a wchar 
literal. Unlike char -> char*, whcar does not implicitly 
convert to wchar*, but you can use the .ptr property.


enum baseClass = "BaseClass"w;
wc.lpszClassName = baseClass.ptr;


Is the only difference between this and private static immutable 
values that the enum could not be an lvalue and has no reference 
at runtime?





Re: Silent error when using hashmap

2017-07-27 Thread Mike Parker via Digitalmars-d

On Thursday, 27 July 2017 at 00:07:39 UTC, FatalCatharsis wrote:

I figured this was the case. WM_NCCREATE is probably sent first 
and the lookup fails. I'm more concerned with why there was no 
exceptions/debug output of any kind.


There are a few things going on with your code. I'll break it 
down one at a time.


1. You can't expect exceptions thrown in a callback called from C 
to be propagated through the C side back into the D side. That 
includes errors. It happens on some platforms, but not all. On 
Windows, it does not (at least, not with DMD -- I can't speak for 
LDC).


2. The error you're getting is because neither WM_CREATE nore 
WM_NCCREATE is the first message sent. You can see this by 
inserting the following into your WndProc:


```
static UINT first;
if(msg == WM_NCCREATE) {
try {
if(first == 0) writeln("NCCREATE is first");
else writeln("First is ", first);
}
catch(Exception e){}
}
else {
// window = winMap[hwnd];
if(first == 0) first = msg;
}
```

This prints 36, which if you look it up (hexcode on MSDN, but I 
like the list at WineHQ [1]) will show you is WM_GETMINMAXINFO. 
That means that when you try to fetch the window instance from 
winMap, there's nothing there. When you try to access a 
non-extent element in an AA, you get a RangeError. Because of 
point 1 above, you're never seeing it and instead are getting a 
crash.


You could try to catch the error and stash it for later, but 
better to do change the way you access the map:


```
if(auto pwin = hwnd in winMap) window = *pwin;
```

The in operator returns a pointer, so it needs to be dereferenced.

3. As I mentioned in another post in this thread, you are doing 
the wrong thing with your window reference. In your call to 
CreateWindowEx, you are correctly casting the reference to void*. 
Everywhere else, you're treating it as a pointer. That's wrong! 
To prove it, you can to this. Declare an instance of WinThing at 
the top of the file.


```
WinThing testMe;
```

Then, add this in the class constructor *before* the call to 
CreateWindowEx.


```
testMe = this;
```

Finally, where you handle the WM_NCCREATE message, do this:

```
try writeln("window is testMe = ", *window is testMe);
catch(Exception e) {}
```

This will print false. Why? Because the window instance you 
created is a reference. In CreateWindowEx, you've treated it as 
such. But then when you fetch it out of lpCreateParams, you cast 
it to a WinThing*. For that to be correct, you would have to 
change CreateWindowEx to pass a pointer to the reference (i.e. 
cast(void*)). But actually, that's still not correct 
because you're taking the address of a local variable. So the 
correct thing to do is to leave CreateWindowEx as is, and change 
all every WinThing* to WinThing.


```
WinThing[HWND] winMap;

WinThing window;
window = cast(WinThing)createStruct.lpCreateParams;
```

Note that you don't have to dereference the createStruct pointer 
to access its fields.


Fix these these issues and it should compile. One other thing, in 
case you are unaware (not an error, just a matter of style).


```
private static string BASE_CLASS = "BaseClass";
```

There's no reason to make this static member or to call toUTFz 
when you use it. You can use a manifest constant with a wchar 
literal. Unlike char -> char*, whcar does not implicitly convert 
to wchar*, but you can use the .ptr property.


enum baseClass = "BaseClass"w;
wc.lpszClassName = baseClass.ptr;

[1] https://wiki.winehq.org/List_Of_Windows_Messages



Re: Silent error when using hashmap

2017-07-27 Thread Steven Schveighoffer via Digitalmars-d

On 7/26/17 10:30 PM, FatalCatharsis wrote:

On Thursday, 27 July 2017 at 01:21:40 UTC, Steven Schveighoffer wrote:
the writeln("start"); and writeln("end"); in main. This is what I 
meant by printing. These do not appear in the output. The programs 
starts and immediately ends without printing "start" and "end".


try flushing the output. In some cases the output streams do not flush 
on newlines.


I did not put an output in the exception handler of the WndProc 
because writeln can throw and the function is marked nothrow. All I 
as trying to do there was get it to recover.


Just surround writeln with try/catch(Exception), should work.

You could also just use good old printf.



This appears to be it. When an error is thrown, stdout does not flush. 
When I put stdout.flush() immediately after the writeln("start") at the 
beginning it is printed correctly. However, when I try to catch the 
error and then do stdout.flush() in main, it does not print.


Do you know of a way to make D always flush the output buffer when an 
error is thrown?


Are you sure the error is being caught? I thought the event loop was run 
in a separate thread. Not sure, because I don't do windows development.


Try catching the error right in the event handler.

-Steve


Re: Silent error when using hashmap

2017-07-26 Thread FoxyBrown via Digitalmars-d

On Thursday, 27 July 2017 at 02:30:17 UTC, FatalCatharsis wrote:
On Thursday, 27 July 2017 at 01:21:40 UTC, Steven Schveighoffer 
wrote:

[...]


This appears to be it. When an error is thrown, stdout does not 
flush. When I put stdout.flush() immediately after the 
writeln("start") at the beginning it is printed correctly. 
However, when I try to catch the error and then do 
stdout.flush() in main, it does not print.


Do you know of a way to make D always flush the output buffer 
when an error is thrown?


On Thursday, 27 July 2017 at 01:05:28 UTC, ketmar wrote:

[...]


Yes, I understand this. This is not my question. My question is 
why all previous output to the console does not occur before 
the error is thrown. As Steve said, this is because the output 
buffer is not flushed when an error occurs.


I just noticed this without an exception. I changed my writeln's 
to write and printed a "\n" but it did not flush. Had to flush it 
manually. Not sure if that is by design or what.


Re: Silent error when using hashmap

2017-07-26 Thread FatalCatharsis via Digitalmars-d
On Thursday, 27 July 2017 at 01:21:40 UTC, Steven Schveighoffer 
wrote:
the writeln("start"); and writeln("end"); in main. This is 
what I meant by printing. These do not appear in the output. 
The programs starts and immediately ends without printing 
"start" and "end".


try flushing the output. In some cases the output streams do 
not flush on newlines.


I did not put an output in the exception handler of the 
WndProc because writeln can throw and the function is marked 
nothrow. All I as trying to do there was get it to recover.


Just surround writeln with try/catch(Exception), should work.

You could also just use good old printf.

-Steve


This appears to be it. When an error is thrown, stdout does not 
flush. When I put stdout.flush() immediately after the 
writeln("start") at the beginning it is printed correctly. 
However, when I try to catch the error and then do stdout.flush() 
in main, it does not print.


Do you know of a way to make D always flush the output buffer 
when an error is thrown?


On Thursday, 27 July 2017 at 01:05:28 UTC, ketmar wrote:
'cause, as i said, RangeError is not an exception. i thought 
that you already know it, as this is "general", not "learning" 
NG.


Yes, I understand this. This is not my question. My question is 
why all previous output to the console does not occur before the 
error is thrown. As Steve said, this is because the output buffer 
is not flushed when an error occurs.




Re: Silent error when using hashmap

2017-07-26 Thread Steven Schveighoffer via Digitalmars-d

On 7/26/17 8:51 PM, FatalCatharsis wrote:

On Thursday, 27 July 2017 at 00:48:48 UTC, ketmar wrote:

FatalCatharsis wrote:


On Thursday, 27 July 2017 at 00:34:28 UTC, ketmar wrote:
wrap the whole event handler function in `try/catch` block, and 
print it there. after all, this is what Dmain does, and so can you. 
having *full* stack trace has no sense there anyway, as you know for 
sure that event handler is called by windows, not by you (and 
usually from your event loop anyway, so detailed stack trace has 
little useful info).


I tried that like so:

https://gist.github.com/FatalCatharsis/39c5f35ae78ecd5399eebe0fb2491004

I put exception blocks both around main and around the invocation of 
the hash lookup and still get no printouts anywhere, including at the 
beginning and end of main.


'cause you never printed anything.


the writeln("start"); and writeln("end"); in main. This is what I meant 
by printing. These do not appear in the output. The programs starts and 
immediately ends without printing "start" and "end".


try flushing the output. In some cases the output streams do not flush 
on newlines.


I did not put an 
output in the exception handler of the WndProc because writeln can throw 
and the function is marked nothrow. All I as trying to do there was get 
it to recover.


Just surround writeln with try/catch(Exception), should work.

You could also just use good old printf.

-Steve


Re: Silent error when using hashmap

2017-07-26 Thread ketmar via Digitalmars-d

FatalCatharsis wrote:


On Thursday, 27 July 2017 at 00:48:48 UTC, ketmar wrote:

FatalCatharsis wrote:


On Thursday, 27 July 2017 at 00:34:28 UTC, ketmar wrote:
wrap the whole event handler function in `try/catch` block, and print 
it there. after all, this is what Dmain does, and so can you. having 
*full* stack trace has no sense there anyway, as you know for sure 
that event handler is called by windows, not by you (and usually from 
your event loop anyway, so detailed stack trace has little useful 
info).


I tried that like so:

https://gist.github.com/FatalCatharsis/39c5f35ae78ecd5399eebe0fb2491004

I put exception blocks both around main and around the invocation of 
the hash lookup and still get no printouts anywhere, including at the 
beginning and end of main.


'cause you never printed anything.


the writeln("start"); and writeln("end"); in main. This is what I meant 
by printing. These do not appear in the output. The programs starts and 
immediately ends without printing "start" and "end". I did not put an 
output in the exception handler of the WndProc because writeln can throw 
and the function is marked nothrow. All I as trying to do there was get 
it to recover.


'cause, as i said, RangeError is not an exception. i thought that you 
already know it, as this is "general", not "learning" NG.


Re: Silent error when using hashmap

2017-07-26 Thread FatalCatharsis via Digitalmars-d

On Thursday, 27 July 2017 at 00:48:48 UTC, ketmar wrote:

FatalCatharsis wrote:


On Thursday, 27 July 2017 at 00:34:28 UTC, ketmar wrote:
wrap the whole event handler function in `try/catch` block, 
and print it there. after all, this is what Dmain does, and 
so can you. having *full* stack trace has no sense there 
anyway, as you know for sure that event handler is called by 
windows, not by you (and usually from your event loop anyway, 
so detailed stack trace has little useful info).


I tried that like so:

https://gist.github.com/FatalCatharsis/39c5f35ae78ecd5399eebe0fb2491004

I put exception blocks both around main and around the 
invocation of the hash lookup and still get no printouts 
anywhere, including at the beginning and end of main.


'cause you never printed anything.


the writeln("start"); and writeln("end"); in main. This is what I 
meant by printing. These do not appear in the output. The 
programs starts and immediately ends without printing "start" and 
"end". I did not put an output in the exception handler of the 
WndProc because writeln can throw and the function is marked 
nothrow. All I as trying to do there was get it to recover.


Re: Silent error when using hashmap

2017-07-26 Thread ketmar via Digitalmars-d

FatalCatharsis wrote:


On Thursday, 27 July 2017 at 00:34:28 UTC, ketmar wrote:
wrap the whole event handler function in `try/catch` block, and print it 
there. after all, this is what Dmain does, and so can you. having *full* 
stack trace has no sense there anyway, as you know for sure that event 
handler is called by windows, not by you (and usually from your event 
loop anyway, so detailed stack trace has little useful info).


I tried that like so:

https://gist.github.com/FatalCatharsis/39c5f35ae78ecd5399eebe0fb2491004

I put exception blocks both around main and around the invocation of the 
hash lookup and still get no printouts anywhere, including at the 
beginning and end of main.


besides, RangeError is not Exception.


Re: Silent error when using hashmap

2017-07-26 Thread ketmar via Digitalmars-d

FatalCatharsis wrote:


On Thursday, 27 July 2017 at 00:34:28 UTC, ketmar wrote:
wrap the whole event handler function in `try/catch` block, and print it 
there. after all, this is what Dmain does, and so can you. having *full* 
stack trace has no sense there anyway, as you know for sure that event 
handler is called by windows, not by you (and usually from your event 
loop anyway, so detailed stack trace has little useful info).


I tried that like so:

https://gist.github.com/FatalCatharsis/39c5f35ae78ecd5399eebe0fb2491004

I put exception blocks both around main and around the invocation of the 
hash lookup and still get no printouts anywhere, including at the 
beginning and end of main.


'cause you never printed anything.


Re: Silent error when using hashmap

2017-07-26 Thread FatalCatharsis via Digitalmars-d

On Thursday, 27 July 2017 at 00:34:28 UTC, ketmar wrote:
wrap the whole event handler function in `try/catch` block, and 
print it there. after all, this is what Dmain does, and so can 
you. having *full* stack trace has no sense there anyway, as 
you know for sure that event handler is called by windows, not 
by you (and usually from your event loop anyway, so detailed 
stack trace has little useful info).


I tried that like so:

https://gist.github.com/FatalCatharsis/39c5f35ae78ecd5399eebe0fb2491004

I put exception blocks both around main and around the invocation 
of the hash lookup and still get no printouts anywhere, including 
at the beginning and end of main.


Re: Silent error when using hashmap

2017-07-26 Thread ketmar via Digitalmars-d

FatalCatharsis wrote:


On Thursday, 27 July 2017 at 00:12:20 UTC, ketmar wrote:
'cause windows' event handler called from darkes depths of windows code, 
and D just can't make sense of the stack to unwind it properly and to 
show you error message and stack trace. never ever rely on getting 
proper stack traces for exceptions thrown in windows callbacks: it *may* 
work sometimes, but it is not guaranteed.


Is there a way to get it to not fail so hard so that prints that occur 
before and after the failure aren't lost? The "begin" and "end" in the 
main don't even get output when the failure happens.


wrap the whole event handler function in `try/catch` block, and print it 
there. after all, this is what Dmain does, and so can you. having *full* 
stack trace has no sense there anyway, as you know for sure that event 
handler is called by windows, not by you (and usually from your event loop 
anyway, so detailed stack trace has little useful info).


Re: Silent error when using hashmap

2017-07-26 Thread FatalCatharsis via Digitalmars-d

On Thursday, 27 July 2017 at 00:12:20 UTC, ketmar wrote:
'cause windows' event handler called from darkes depths of 
windows code, and D just can't make sense of the stack to 
unwind it properly and to show you error message and stack 
trace. never ever rely on getting proper stack traces for 
exceptions thrown in windows callbacks: it *may* work 
sometimes, but it is not guaranteed.


Is there a way to get it to not fail so hard so that prints that 
occur before and after the failure aren't lost? The "begin" and 
"end" in the main don't even get output when the failure happens.





Re: Silent error when using hashmap

2017-07-26 Thread ketmar via Digitalmars-d

FatalCatharsis wrote:


On Wednesday, 26 July 2017 at 16:39:15 UTC, ketmar wrote:>
'cause `WM_CREATE` is not the first message window receiving. check if 
hwnd is in hash with `in` first.


I figured this was the case. WM_NCCREATE is probably sent first and the 
lookup fails. I'm more concerned with why there was no exceptions/debug 
output of any kind.


'cause windows' event handler called from darkes depths of windows code, 
and D just can't make sense of the stack to unwind it properly and to show 
you error message and stack trace. never ever rely on getting proper stack 
traces for exceptions thrown in windows callbacks: it *may* work sometimes, 
but it is not guaranteed.


Re: Silent error when using hashmap

2017-07-26 Thread FatalCatharsis via Digitalmars-d

On Wednesday, 26 July 2017 at 16:39:15 UTC, ketmar wrote:>
'cause `WM_CREATE` is not the first message window receiving. 
check if hwnd is in hash with `in` first.


I figured this was the case. WM_NCCREATE is probably sent first 
and the lookup fails. I'm more concerned with why there was no 
exceptions/debug output of any kind.


On Wednesday, 26 July 2017 at 22:08:45 UTC, Steven Schveighoffer 
wrote:
Note that in D when a thread crashes besides the main thread, 
you may not get a stack trace printout. You may get nothing.


-Steve


This example doesn't create any threads explicitly. Are there 
other threads that dlang generates? How do I obtain debug output 
and proper exception handling from these threads?





Re: Silent error when using hashmap

2017-07-26 Thread Steven Schveighoffer via Digitalmars-d

On 7/26/17 12:09 PM, FatalCatharsis wrote:
I apologize, I'm not sure if this is expected behavior, a bug in the 
compiler, or a bug in the core windows libraries, so I'll post this here 
until pointed elsewhere.


I've done this trick with win32 for awhile in other languages where I 
pass a reference to a specific class of my own that represents an 
instance of window to the CreateWindowEx function, and then use a static 
router function to send messages to the specific instance. I've made the 
most minimal example I can in this gist.


https://gist.github.com/FatalCatharsis/d3cc6ec621f0600975806fe23610ae32

When I compile this and run this, nothing is printed and no window is 
created. I've tried putting try catches around everything (including the 
inside of the static constructor), but nothing is caught.


Note that in D when a thread crashes besides the main thread, you may 
not get a stack trace printout. You may get nothing.


-Steve


Re: Silent error when using hashmap

2017-07-26 Thread Mike Parker via Digitalmars-d

On Wednesday, 26 July 2017 at 16:09:30 UTC, FatalCatharsis wrote:



When I compile this and run this, nothing is printed and no 
window is created. I've tried putting try catches around 
everything (including the inside of the static constructor), 
but nothing is caught.


You're casting this to void*, which is correct, but then when you 
fetch it back you're casting to a WinThing*, which is not 
correct. this is a reference, not a pointer. Cast to WinThing 
instead of WinThing*.


Re: Silent error when using hashmap

2017-07-26 Thread ketmar via Digitalmars-d

FatalCatharsis wrote:

I apologize, I'm not sure if this is expected behavior, a bug in the 
compiler, or a bug in the core windows libraries, so I'll post this here 
until pointed elsewhere.


I've done this trick with win32 for awhile in other languages where I 
pass a reference to a specific class of my own that represents an 
instance of window to the CreateWindowEx function, and then use a static 
router function to send messages to the specific instance. I've made the 
most minimal example I can in this gist.


https://gist.github.com/FatalCatharsis/d3cc6ec621f0600975806fe23610ae32

When I compile this and run this, nothing is printed and no window is 
created. I've tried putting try catches around everything (including the 
inside of the static constructor), but nothing is caught.


However, when I comment out the hash lookup on line 54, the compiled 
program runs fine and creates a window, (but only for a moment since 
there is not a message handling loop). The expected printout of "start" 
and "end" occurs just fine.


What is happening here that causes the program not execute at all, with 
no output and no exceptions? Is this a bug with my code, a bug with the 
core.sys.windows.windows library, or a bug with the compiler? Any info 
about how to debug this further is greatly appreciated.


'cause `WM_CREATE` is not the first message window receiving. check if hwnd 
is in hash with `in` first.


Silent error when using hashmap

2017-07-26 Thread FatalCatharsis via Digitalmars-d
I apologize, I'm not sure if this is expected behavior, a bug in 
the compiler, or a bug in the core windows libraries, so I'll 
post this here until pointed elsewhere.


I've done this trick with win32 for awhile in other languages 
where I pass a reference to a specific class of my own that 
represents an instance of window to the CreateWindowEx function, 
and then use a static router function to send messages to the 
specific instance. I've made the most minimal example I can in 
this gist.


https://gist.github.com/FatalCatharsis/d3cc6ec621f0600975806fe23610ae32

When I compile this and run this, nothing is printed and no 
window is created. I've tried putting try catches around 
everything (including the inside of the static constructor), but 
nothing is caught.


However, when I comment out the hash lookup on line 54, the 
compiled program runs fine and creates a window, (but only for a 
moment since there is not a message handling loop). The expected 
printout of "start" and "end" occurs just fine.


What is happening here that causes the program not execute at 
all, with no output and no exceptions? Is this a bug with my 
code, a bug with the core.sys.windows.windows library, or a bug 
with the compiler? Any info about how to debug this further is 
greatly appreciated.