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 version (Windows): 16 17 import ae.sys.windows.imports; 18 mixin(importWin32!q{winbase}); 19 mixin(importWin32!q{windef}); 20 21 import ae.sys.windows.exception; 22 23 /// Loads or retrieves the handle of a DLL. 24 /// As there will be only one template instantiation 25 /// per unique DLL string, LoadLibrary will be called 26 /// at most once per unique "dll" parameter. 27 @property HMODULE moduleHandle(string dll)() 28 { 29 static HMODULE hModule = null; 30 if (!hModule) 31 hModule = LoadLibrary(dll).wenforce("LoadLibrary"); 32 return hModule; 33 } 34 35 /// Given a static function declaration, generate a loader with the same name in the current scope 36 /// that loads the function dynamically from the given DLL. 37 mixin template DynamicLoad(alias F, string DLL, string NAME=__traits(identifier, F)) 38 { 39 static import std.traits; 40 41 static std.traits.ReturnType!F loader(ARGS...)(ARGS args) 42 { 43 alias typeof(&F) FP; 44 static FP fp = null; 45 if (!fp) 46 fp = cast(FP)wenforce(GetProcAddress(moduleHandle!DLL, NAME), "GetProcAddress"); 47 return fp(args); 48 } 49 50 mixin(`alias loader!(std.traits.ParameterTypeTuple!F) ` ~ NAME ~ `;`); 51 } 52 53 /// Ditto 54 mixin template DynamicLoadMulti(string DLL, FUNCS...) 55 { 56 static if (FUNCS.length) 57 { 58 mixin DynamicLoad!(FUNCS[0], DLL); 59 mixin DynamicLoadMulti!(DLL, FUNCS[1..$]); 60 } 61 } 62 63 version(unittest) mixin(importWin32!q{winuser}); 64 65 /// 66 unittest 67 { 68 mixin DynamicLoad!(GetVersion, "kernel32.dll"); 69 GetVersion(); // called via GetProcAddress 70 71 // Multiple imports 72 mixin DynamicLoadMulti!("user32.dll", GetDC, ReleaseDC); 73 }