Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
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.
// 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