Here are some random notes and thoughs mainly for D developers, about different problems I had and how I bypassed them.
First of all, all the stuff in pixeltoaster is placed in PixelToaster namespace. D doesn't like C++ namespaces, that's the reason, I've created PixelToasterWrapper.
It's a minimalistic piece of code in cpp, that provides simple layer between D's PixelToastereD and C++'es pixeltoaster.
Under Linux it's simply wrapper for functions from pixeltoaster namespace.
Under Windows it dynamically loads pixeltoaster.dll library via LoadLibrary, parses headers and tries to find functions that matches createDisplay and createTimer.
There are some IDisplay and ITimer dummies, iirc this is for dmc, so it can generate proper symbols (I'm not sure right now, but I think if I tried to use PixelToaster::DisplayInterface*, the generated symbols weren't right, and later dmd couldn't find them).
I've simply rewritten TrueColorPixel and FloatingColorPixel structs to D, this was quite obvious since otherwise it'd be quite inconvenient to use make any use of pixeltoaster :>
I've also rewritten Mouse struct.
PixelToastereD.Display is simply a copy of a PixelToaster::Display class.
There are some differences (like throwing exceptions, wrapper is missing ATM).
There are some differences in mode(), output() and listener(...), but I'll describe them further.
I think this is the most important thing in PixelToastered.
There are almost two different interfaces (one for MSVC, and one that we can call normal :>)
normal IDisplay is basically a copy of a PixelToaster::DisplayInterface abstract-base-class, and everything seems to be working fine.
MSVC however does some crazy things. If there are overloads for the method with given name, it seems that it place the ptrs in vtbl "near-each-other".
That wouldn't be a big problem we could simply change order in header file, and everything should be fine...
..but things get strange now, it seems that if you place overloaded name (in header file) one-next to each other like:
... virtual void listener( class Listener * listener ) = 0; virtual class Listener* listener() const = 0; ...
MSVC (at least 2005 on which I've done the tests) places pointers in vtbl ALWAYS in reverse order.
(We can argue if getters/setters should be named like that, but that's not the point here :P)
That's why there's one big version block in IDisplay
There is one more difference in case of mode() and output().
They both return object using "return-by-value" semantic.
First take a look at following link: http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.9
MSVC seems to be using figuring-out the case and does exactly what is describes in link above. (In fact that means it calls assignment operator).
Because of that, code like (C++):
Mode m = display->mode();
is tranlated to something like (pseudo-code):
Mode m; display->copyInternalMode(&m);
and that's exactly why IDisplay.mode() and IDisplay.output(), have the following signature in case of MSVC:
void mode(ref ModeCPP data) const; void output(ref OutputCPP data) const;
(If you ask - why, well, otherwise stack get smashed :>)
version(UseDListener) is nothing really fancy, but I didn't like extern(C++) in my D code ;P
When listener is registrated there is created simple dummy, that inherits after C++ interface and passes all the callbacks to the upper D-listener.