Last active
March 8, 2018 13:46
-
-
Save dkorpel/3bf108ca48cb43bdbe3cc8bf30405b4d to your computer and use it in GitHub Desktop.
D code that generates function pointers to DLL functions when a struct with declarations is given. It can be used when you don't want to manually generate all the boilerplate for it and you don't want to use an import library.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Member function names and signatures correspond to those in the DLL | |
struct FunctionsInMyDLL { | |
int getVersion(); | |
string getName(); | |
// more functions | |
} | |
import std.traits: ReturnType, Parameters, fullyQualifiedName; | |
// This template generates a C function pointer type from a member function in the struct | |
// extern(C) must be around this alias, putting it around the mixin template does not work | |
extern(C) alias CFunctionPointer(alias f) = ReturnType!f function(Parameters!f); | |
// This mixin generates function pointers from the given struct as well as aliases for their types | |
// prefixed with 't_'. So 'getVersion' has type 't_getVersion'. These aliases make casting the void* easier | |
mixin template declareCFunctionPointers(Struct) { | |
static foreach(memberName; [ __traits(allMembers, Struct) ]) { | |
mixin("alias t_"~memberName~"= CFunctionPointer!("~fullyQualifiedName!Struct~"."~memberName~");"); | |
mixin("t_" ~ memberName ~ " " ~ memberName ~ ";"); | |
} | |
} | |
// Instantiate the template at module scope | |
mixin declareCFunctionPointers!FunctionsInMyDLL; | |
// Loads a DLL and binds all function pointers as declared in a given struct (Windows only) | |
void loadDLLFunctions(Struct)(void* handle) { | |
import core.sys.windows.windows: GetProcAddress; | |
import std.exception: enforce; | |
import std.string: toStringz; | |
static foreach(memberName; [ __traits(allMembers, Struct) ]) { | |
mixin(memberName~` = cast(t_`~memberName~`) enforce(GetProcAddress(handle, "`~memberName~`".toStringz), "function `~memberName~` could not be found in DLL");`); | |
} | |
} | |
// Example of loading a DLL in windows | |
void main() { | |
import core.sys.windows.windows: LoadLibrary; | |
import std.exception: enforce; | |
import std.stdio: writeln; | |
auto handle = enforce(LoadLibrary("mydll.dll"), "mydll not found"); | |
loadDLLFunctions!FunctionsInMyDLL(handle); | |
// Function pointers are now loaded, so we can call DLL functions | |
writeln(getName(), "version", getVersion()); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment