1 /** 2 * Windows DLL utility code. 3 * 4 * License: 5 * This Source Code Form is subject to the terms of 6 * the Mozilla Public License, v. 2.0. If a copy of 7 * the MPL was not distributed with this file, You 8 * can obtain one at http://mozilla.org/MPL/2.0/. 9 * 10 * Authors: 11 * Vladimir Panteleev <vladimir@thecybershadow.net> 12 */ 13 14 module ae.sys.windows.dll; 15 16 17 import win32.winbase; 18 import win32.windef; 19 20 import ae.sys.windows.exception; 21 22 /// Loads or retrieves the handle of a DLL. 23 /// As there will be only one template instantiation 24 /// per unique DLL string, LoadLibrary will be called 25 /// at most once per unique "dll" parameter. 26 @property HMODULE moduleHandle(string dll)() 27 { 28 static HMODULE hModule = null; 29 if (!hModule) 30 hModule = LoadLibrary(dll).wenforce("LoadLibrary"); 31 return hModule; 32 } 33 34 /// Given a static function declaration, generate a loader with the same name in the current scope 35 /// that loads the function dynamically from the given DLL. 36 mixin template DynamicLoad(alias F, string DLL, string NAME=__traits(identifier, F)) 37 { 38 static import std.traits; 39 40 static std.traits.ReturnType!F loader(ARGS...)(ARGS args) 41 { 42 alias typeof(&F) FP; 43 static FP fp = null; 44 if (!fp) 45 fp = cast(FP)wenforce(GetProcAddress(moduleHandle!DLL, NAME), "GetProcAddress"); 46 return fp(args); 47 } 48 49 mixin(`alias loader!(std.traits.ParameterTypeTuple!F) ` ~ NAME ~ `;`); 50 } 51 52 /// Ditto 53 mixin template DynamicLoad(string DLL, FUNCS...) 54 { 55 static if (FUNCS.length) 56 { 57 mixin DynamicLoad!(FUNCS[0], DLL); 58 mixin DynamicLoad!(DLL, FUNCS[1..$]); 59 } 60 } 61 62 version(unittest) import win32.winuser; 63 64 /// 65 unittest 66 { 67 mixin DynamicLoad!(GetVersion, "kernel32.dll"); 68 GetVersion(); // called via GetProcAddress 69 70 // Multiple imports 71 mixin DynamicLoad!("user32.dll", GetDC, ReleaseDC); 72 }