Skip to content

Instantly share code, notes, and snippets.

@rikkimax
Created March 22, 2015 16:06
Show Gist options
  • Save rikkimax/d856f1b26ddb321a0b95 to your computer and use it in GitHub Desktop.
Save rikkimax/d856f1b26ddb321a0b95 to your computer and use it in GitHub Desktop.
//exe
module webdev.webserver.modulebase.init;
export:
void onModuleLoad();
void onModuleUnload();
//exe
import std.stdio;
void main()
{
import webdev.webserver.modules.loader;
import webdev.webserver.modules.defs;
ModLoader!WebServerModuleInterface loader;
loader.load("webserver_modulebase.dll");
}
//exe
module webdev.webserver.modules.defs;
struct WebServerModuleInterface {
@("webdev.webserver.modulebase.init") {
void function() onModuleLoad;
void function() onModuleUnload;
}
}
//dll
module webdev.webserver.modulebase.init;
export:
void onModuleLoad() {
import std.stdio;
writeln("onModuleLoad");
}
void onModuleUnload() {
import std.stdio;
writeln("onModuleUnload");
}
//exe
module webdev.webserver.modules.loader;
import derelict.util.loader;
struct ModLoader(T) if (is(T == struct)) {
private __gshared {
size_t counter;
LoaderSharedLibrary!T[size_t] loaders;
string[] searchLocations_;
}
this(string[] locations...) {
searchLocations_ = locations;
}
@property {
void searchLocations(string[] locations) {
searchLocations_ = locations;
}
const(string[]) searchLocations() {
return cast(const)searchLocations_;
}
size_t[] validIds() {
return loaders.keys;
}
LoaderSharedLibrary!T opIndex(size_t id) {
if (id in loaders)
return loaders[id];
return null;
}
}
void searchLocations(string[] locations...) {
searchLocations_ = locations;
}
void addSearchLocations(string[] locations...) {
searchLocations_ ~= locations;
}
size_t load(string[] name...) {
size_t id = counter;
loaders[id] = new LoaderSharedLibrary!T(name, searchLocations_);
loaders[id].load();
loaders[id].onModuleLoad();
counter++;
return id;
}
void unload(size_t id) {
if (id in loaders) {
loaders[id].onModuleUnload();
loaders[id].unload;
loaders.remove(id);
}
}
}
private {
class LoaderSharedLibrary(T) : SharedLibLoader {
T me;
alias me this;
protected {
override void loadSymbols() {
import std.traits : isFunctionPointer;
foreach(member; __traits(allMembers, T)) {
mixin("alias MTYPE = typeof(T." ~ member ~ ");");
static if (isFunctionPointer!MTYPE) {
enum attributes = __traits(getAttributes, mixin("T." ~ member));
static if (attributes.length == 1) {// FIXME: should be check if it is a string!
mixin("import theModule = " ~ attributes[0] ~ ";");
mixin("enum mangled = theModule." ~ member ~ ".mangleof;");
mixin("alias MMTYPE = typeof(theModule." ~ member ~ ");");
static assert(__traits(compiles, member ~ " = &theModule." ~ member ~ ";"), "Struct declaration does not match the stub version.");
void* value;
bindFunc(&value, mangled, false);
version(Windows) {
version(X86) {
if (value is null)
bindFunc(&value, mangled[1 .. $]);
} else {
if (value is null)
assert(0);
}
} else {
if (value is null)
assert(0);
}
mixin(member ~ " = cast(MTYPE)value;");
}
}
}
}
}
this(string[] binaries, string[] searchLocations) {
import std.path : buildPath;
string modifiedPaths;
if (searchLocations.length > 0 && binaries.length > 0) {
foreach(loc; searchLocations) {
foreach(bin; binaries) {
modifiedPaths ~= buildPath(loc, bin) ~ ",";
}
}
} else if (binaries.length > 0) {
foreach(bin; binaries) {
modifiedPaths ~= bin ~ ",";
}
}
if (binaries.length > 0)
modifiedPaths.length--;
super(modifiedPaths);
}
}
}
//dll
module webdev.webserver.modulebase.main;
import webdev.webserver.modulebase.init;
void fixStandardIO() {
import std.stdio: stdin, stdout, stderr, File;
// Loads up new instances of stdin/stdout/stderr if they have not been properly created
if (stdin.error || stdout.error || stderr.error) {
version(Windows) {
import core.sys.windows.windows: GetStdHandle, STD_INPUT_HANDLE, STD_OUTPUT_HANDLE, STD_ERROR_HANDLE;
File nstdin;
nstdin.windowsHandleOpen(GetStdHandle(STD_INPUT_HANDLE), ['r']);
stdin = nstdin;
File nstdout;
nstdout.windowsHandleOpen(GetStdHandle(STD_OUTPUT_HANDLE), ['w']);
stdout = nstdout;
File nstderr;
nstderr.windowsHandleOpen(GetStdHandle(STD_ERROR_HANDLE), ['w']);
stderr = nstderr;
}
}
}
shared static this() {
fixStandardIO();
}
version(Windows) {
import core.sys.windows.dll;
mixin SimpleDllMain;
} else {
void main(){} // is this even needed?
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment