The issue with libraries that use Windows API prototypes

Andrej Mitrovic andrej.mitrovich at gmail.com
Sat Jul 9 09:55:54 PDT 2011


I've run into yet another incompatibility issue with D2 libraries that
use the Windows API.
This time it's Derelict:

testderelict.obj(testderelict)
 Error 42: Symbol Undefined _wglDeleteContext at 4
testderelict.obj(testderelict)
 Error 42: Symbol Undefined _wglMakeCurrent at 8
testderelict.obj(testderelict)
 Error 42: Symbol Undefined _wglCreateContext at 4
--- errorlevel 3

The issue? Derelict uses its own Windows API header prototype in
\Derelict2\DerelictUtil\derelict\util, which defines:

alias void* HANDLE;
alias HANDLE HGLRC;

And the "_wgl" functions take HGLRC as the parameter.

The problem is WindowsAPI also defines these, because well, it's a
binding library so it has to. And it's prototypes are:

typedef void* HANDLE;
alias HANDLE HGLRC;

When linking my project with WinsowsAPI and Derelict, the Derelict
static library defines a function as "_wglDeleteContext", while the
project that uses WindowsAPI sees the wglDeleteContext prototype from
the import, but sees the HGLRC typedef in WindowsAPI, and DMD looks
for the symbol "_wglDeleteContext at 4".

So now I can't really use Derelict and the WindowsAPI. Perhaps I can
use it with std.c.windows.windows? Nope, guess again!

std.c.windows.windows doesn't define NULL (small nuisance), and it
doesn't use aliases to ANSI/WideChar versions of API functions like
the WindowsAPI bindings, you have to explicitly use e.g. MessageBoxA
or MessageBoxW.

To add insult to injury, MessageBoxW isn't even defined in
\druntime\src\core\sys\windows\windows.d (that's imported by
std.c.windows.windows). It defines maybe 5% of anything in WindowsAPI,
so using std.c.windows.windows is out of the question because of an
enormous wall of errors due to missing symbols.

But even so, std.c.windows.windows *also* defines HANDLE:
typedef void *HANDLE;

So far, we have 3 incompatible libraries. Add a couple of more
libraries like DFL, DGui DCairo and now we're up to 6.

*Every single* Windows-related library seems to define its own winapi
prototypes, and because of issues like:
1. typedefs (which we're going to hopefully kill sometime soon)
2. small differences in how these prototypes were written

these libraries become incompatible with each other. It's only going
to get worse as each library author keeps growing their library and
adds more prototypes.

I can see two ways out of this situation:
1) D Library authors start using the WindowsAPI bindings from
http://dsource.org/projects/bindings/wiki/WindowsApi, and expect the
user of the their library to put WindowsAPI in the import path where
the authors' libraries can find it to resolve symbols, and where the
user's project can import it as well. This would mean the author's
library's build process gets a bit more complicated as you would have
to pass the path to the WindowsAPI bindings when building the author's
library.

2) We devise some plan to incorporate WindowsAPI into Phobos itself.
This way library users don't have to waste time fetching dependencies,
and library authors don't have to waste time prototyping functions
since the majority of this work will be already incorporated into
Phobos.

The DCairo author kindly suggested to use version(WindowsAPI)
else(HisOwnPrototypes) as a workaround, but this doesn't scale. There
could be numerous prototypes based on how many libraries you use.

How #2 can be organized, I don't know. But we have to start from
somewhere because the more time we wait, the worse this situation
gets.


More information about the Digitalmars-d mailing list