www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Runtime Dynamic Linking

This is similar turf to the DDL project, but I couldn't see any examples 
for Windows DLL runtime linking. So I threw this together and while it 
works and I do like it, I'm wondering if it can be improved upon.

It lets you define a way to call a function in a DLL without linking in 
its import library.

So this -

# alias dllimport!("user32.dll", "MessageBoxW", uint, void*, wchar*, 
wchar*, uint) MessageBox;

can be used as you would with a DLL import library, but it's linked at 
runtime -

# MessageBox(null, "Hello", "World", 0);

Now, here's the template code that does the magic.

# template signature(R, T0 = void, T1 = void, T2 = void, T3 = void) {
#   static if (!is(T3 == void))
#     extern (Windows) alias R function(T0, T1, T2, T3) signature;
#   else static if (!is(T2 == void))
#     extern (Windows) alias R function(T0, T1, T2) signature;
#   else static if (!is(T1 == void))
#     extern (Windows) alias R function(T0, T1) signature;
#   else static if (!is(T0 == void))
#     extern (Windows) alias R function(T0) signature;
#   else
#     extern (Windows) alias R function() signature;
# }

# template functor(char[] dllName, char[] entryPoint, R, T0 = void, T1 = 
void, T2 = void, T3 = void) {
#   static if (!is(T3 == void)) {
#     static R opCall(T0 t0, T1 t1, T2 t2, T3 t3) {
#       return (cast(signatureT)GetProcAddress(LoadLibraryA(dllName), 
entryPoint))(t0, t1, t2, t3);
#     }
#   }
#   else static if (!is(T2 == void)) {
#     static R opCall(T0 t0, T1 t1, T2 t2) {
#       return (cast(signatureT)GetProcAddress(LoadLibraryA(dllName), 
entryPoint))(t0, t1, t2);
#     }
#   }
#   else static if (!is(T1 == void)) {
#     static R opCall(T0 t0, T1 t1) {
#       return (cast(signatureT)GetProcAddress(LoadLibraryA(dllName), 
entryPoint))(t0, t1);
#     }
#   }
#   else static if (!is(T0 == void)) {
#     static R opCall(T0 t0) {
#       return (cast(signatureT)GetProcAddress(LoadLibraryA(dllName), 
entryPoint))(t0);
#     }
#   }
#   else {
#     static R opCall() {
#       return (cast(signatureT)GetProcAddress(LoadLibraryA(dllName), 
entryPoint))();
#     }
#   }
# }

# struct dllimport(char[] dllName, char[] entryPoint, R, T0 = void, T1 = 
void, T2 = void, T3 = void) {
#   alias signature!(R, T0, T1, T2, T3) signatureT;
#   mixin functor!(dllName, entryPoint, R, T0, T1, T2, T3);
# }

There are some issues, obviously. FreeLibrary doesn't get called (fairly 
straightforward to solve). And it should check if both the DLL and 
function were found, throwing an exception if not.

My main question is this: can I get rid of the struct, maybe replacing 
it with a delegate? I've been staring at it for so long I can't see the 
alternatives.

Cheers.
Apr 15 2006