Skip to content

Instantly share code, notes, and snippets.

@MrSmith33
Last active August 29, 2015 14:08
Show Gist options
  • Save MrSmith33/8750dd43c0843d45ccf8 to your computer and use it in GitHub Desktop.
Save MrSmith33/8750dd43c0843d45ccf8 to your computer and use it in GitHub Desktop.
Module loading
dmd -debug -g app.d imodule.d
del app.obj
module app;
import std.stdio : writeln, writefln;
import std.string : toStringz;
import imodule;
version (Posix)
{
pragma(lib, "dl");
version (Linux)
{
private import std.c.linux.linux;
}
else
{
extern( C ) nothrow
{
const int RTLD_NOW = 2;
void *dlopen( const( char )* file, int mode );
int dlclose( void* handle );
void *dlsym( void* handle, const( char* ) name );
const( char )* dlerror();
}
}
alias void* SharedLibHandle;
private
{
SharedLibHandle LoadSharedLib( string libName )
{
return dlopen( libName.toStringz(), RTLD_NOW );
}
void UnloadSharedLib( SharedLibHandle hlib )
{
dlclose( hlib );
}
void* GetSymbol( SharedLibHandle hlib, string symbolName )
{
return dlsym( hlib, symbolName.toStringz() );
}
string GetErrorStr()
{
import std.conv : to;
auto err = dlerror();
if( err is null )
return "Uknown Error";
return to!string( err );
}
}
}
else version (Windows)
{
import core.sys.windows.windows;
alias SharedLibHandle = HMODULE;
private
{
SharedLibHandle LoadSharedLib( string libName )
{
return LoadLibraryA( libName.toStringz() );
}
void UnloadSharedLib( SharedLibHandle hlib )
{
FreeLibrary( hlib );
}
void* GetSymbol( SharedLibHandle hlib, string symbolName )
{
return GetProcAddress( hlib, symbolName.toStringz() );
}
string GetErrorStr()
{
import std.windows.syserror;
return sysErrorString( GetLastError() );
}
}
}
else
{
static assert(0);
}
IModule loadSharedModule(string file)
{
import core.runtime;
SharedLibHandle handle;
void* farproc;
handle = cast(SharedLibHandle) Runtime.loadLibrary(file);
if (handle is null)
{
writeln("Error loading ", file);
GetErrorStr().writeln;
return null;
}
farproc = GetSymbol(handle, "getModuleInstance");
if (farproc is null)
{
writeln("Error loading symbol getModuleInstance()");
GetErrorStr().writeln;
return null;
}
alias ModuleFactory = IModule function();
return (*cast(ModuleFactory)farproc)();
}
class ModuleManager : IModuleManager
{
IModule[string] modules;
void registerModule(IModule moduleInstance)
{
assert(moduleInstance);
modules[moduleInstance.name] = moduleInstance;
}
void initModules()
{
foreach(IModule m; modules)
{
m.init(this);
writefln("Inited module %s", m.name);
}
}
override IModule findModule(string moduleName)
{
return modules[moduleName];
}
}
void main()
{
ModuleManager modman = new ModuleManager;
modman.registerModule(loadSharedModule("./sharedmodule1.so"));
modman.registerModule(loadSharedModule("./sharedmodule2.so"));
modman.initModules;
}
dmd -c -ofapp.o app.d imodule.d -debug -g
dmd app.o -L-ldl -defaultlib=libphobos2.so
rm app.o
module dll;
version(Windows):
import core.sys.windows.windows;
import core.sys.windows.dll;
__gshared HINSTANCE g_hInst;
extern (Windows)
BOOL DllMain(HINSTANCE hInstance, ULONG ulReason, LPVOID pvReserved)
{
switch (ulReason)
{
case DLL_PROCESS_ATTACH:
g_hInst = hInstance;
dll_process_attach( hInstance, true );
break;
case DLL_PROCESS_DETACH:
dll_process_detach( hInstance, true );
break;
case DLL_THREAD_ATTACH:
dll_thread_attach( true, true );
break;
case DLL_THREAD_DETACH:
dll_thread_detach( true, true );
break;
default:
assert(0);
}
return true;
}
module imodule;
interface IModule
{
string name();
void init(IModuleManager moduleman);
void* realInterface();
}
interface IModuleManager
{
IModule findModule(string moduleName);
}
module isharedmodule1;
interface ISharedModule1
{
string doItCool();
}
dmd -ofsharedmodule1.dll sharedmodule1.d isharedmodule1.d imodule.d dll.d -shared -g -debug
del sharedmodule1.obj
module sharedmodule1;
import imodule;
import isharedmodule1;
class SharedModule1 : ISharedModule1, IModule
{
override string name()
{
return "SharedModule1";
}
override void init(IModuleManager moduleman)
{
}
override string doItCool()
{
return "Cool stuff";
}
override void* realInterface()
{
return cast(void*)cast(ISharedModule1)this;
}
}
export extern(C) IModule getModuleInstance()
{
return new SharedModule1;
}
#!/bin/sh
dmd -c -ofsharedmodule1.o sharedmodule1.d isharedmodule1.d dll.d -fPIC -g -debug
dmd -ofsharedmodule1.so sharedmodule1.o -shared -defaultlib=libphobos2.so
rm sharedmodule1.o
dmd -ofsharedmodule2.dll sharedmodule2.d imodule.d dll.d isharedmodule1.d -shared -g -debug
del sharedmodule2.obj
module sharedmodule2;
import imodule;
import isharedmodule1;
import std.stdio;
class SharedModule2 : IModule
{
override string name()
{
return "SharedModule2";
}
override void init(IModuleManager moduleman)
{
IModule mod1 = moduleman.findModule("SharedModule1");
writefln("%s", mod1); // prints null instead of SharedModule1. RTTI is missing.
ISharedModule1 smod1 = cast(ISharedModule1)mod1;
writeln(smod1 is null ? "null" : "not null"); // prints null
smod1 = cast(ISharedModule1)mod1.realInterface;
writeln(smod1 is null ? "null" : "not null");
if (smod1)
smod1.doItCool.writeln; // prints Cool stuff. See sharedmodule1
throw new Exception("test"); // Silent fail. App closes.
}
override void* realInterface()
{
return null;
}
}
export extern(C) IModule getModuleInstance()
{
return new SharedModule2;
}
#!/bin/sh
dmd -c -ofsharedmodule2.o sharedmodule2.d isharedmodule1.d dll.d -fPIC -g -debug
dmd -ofsharedmodule2.so sharedmodule2.o -shared -defaultlib=libphobos2.so
rm sharedmodule2.o
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment