309 lines
7.7 KiB
Text
309 lines
7.7 KiB
Text
/* -----------------------------------------------------------------------------
|
|
* wrapperloader.swg
|
|
*
|
|
* Support code for dynamically linking the C wrapper library from the D
|
|
* wrapper module.
|
|
*
|
|
* The loading code was adapted from the Derelict project and is used with
|
|
* permission from Michael Parker, the original author.
|
|
* ----------------------------------------------------------------------------- */
|
|
|
|
%pragma(d) wrapperloadercode = %{
|
|
private {
|
|
version(linux) {
|
|
version = Nix;
|
|
} else version(darwin) {
|
|
version = Nix;
|
|
} else version(OSX) {
|
|
version = Nix;
|
|
} else version(FreeBSD) {
|
|
version = Nix;
|
|
version = freebsd;
|
|
} else version(freebsd) {
|
|
version = Nix;
|
|
} else version(Unix) {
|
|
version = Nix;
|
|
} else version(Posix) {
|
|
version = Nix;
|
|
}
|
|
|
|
version(Tango) {
|
|
static import tango.stdc.string;
|
|
static import tango.stdc.stringz;
|
|
|
|
version (PhobosCompatibility) {
|
|
} else {
|
|
alias char[] string;
|
|
alias wchar[] wstring;
|
|
alias dchar[] dstring;
|
|
}
|
|
} else {
|
|
version(D_Version2) {
|
|
static import std.conv;
|
|
} else {
|
|
static import std.c.string;
|
|
}
|
|
static import std.string;
|
|
}
|
|
|
|
version(D_Version2) {
|
|
mixin("alias const(char)* CCPTR;");
|
|
} else {
|
|
alias char* CCPTR;
|
|
}
|
|
|
|
CCPTR swigToCString(string str) {
|
|
version(Tango) {
|
|
return tango.stdc.stringz.toStringz(str);
|
|
} else {
|
|
return std.string.toStringz(str);
|
|
}
|
|
}
|
|
|
|
string swigToDString(CCPTR cstr) {
|
|
version(Tango) {
|
|
return tango.stdc.stringz.fromStringz(cstr);
|
|
} else {
|
|
version(D_Version2) {
|
|
mixin("return std.conv.to!string(cstr);");
|
|
} else {
|
|
return std.c.string.toString(cstr);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
class SwigSwigSharedLibLoadException : Exception {
|
|
this(in string[] libNames, in string[] reasons) {
|
|
string msg = "Failed to load one or more shared libraries:";
|
|
foreach(i, n; libNames) {
|
|
msg ~= "\n\t" ~ n ~ " - ";
|
|
if(i < reasons.length)
|
|
msg ~= reasons[i];
|
|
else
|
|
msg ~= "Unknown";
|
|
}
|
|
super(msg);
|
|
}
|
|
}
|
|
|
|
class SwigSymbolLoadException : Exception {
|
|
this(string SwigSharedLibName, string symbolName) {
|
|
super("Failed to load symbol " ~ symbolName ~ " from shared library " ~ SwigSharedLibName);
|
|
_symbolName = symbolName;
|
|
}
|
|
|
|
string symbolName() {
|
|
return _symbolName;
|
|
}
|
|
|
|
private:
|
|
string _symbolName;
|
|
}
|
|
|
|
private {
|
|
version(Nix) {
|
|
version(freebsd) {
|
|
// the dl* functions are in libc on FreeBSD
|
|
}
|
|
else {
|
|
pragma(lib, "dl");
|
|
}
|
|
|
|
version(Tango) {
|
|
import tango.sys.Common;
|
|
} else version(linux) {
|
|
import core.sys.posix.dlfcn;
|
|
} else {
|
|
extern(C) {
|
|
const RTLD_NOW = 2;
|
|
|
|
void *dlopen(CCPTR file, int mode);
|
|
int dlclose(void* handle);
|
|
void *dlsym(void* handle, CCPTR name);
|
|
CCPTR dlerror();
|
|
}
|
|
}
|
|
|
|
alias void* SwigSharedLibHandle;
|
|
|
|
SwigSharedLibHandle swigLoadSharedLib(string libName) {
|
|
return dlopen(swigToCString(libName), RTLD_NOW);
|
|
}
|
|
|
|
void swigUnloadSharedLib(SwigSharedLibHandle hlib) {
|
|
dlclose(hlib);
|
|
}
|
|
|
|
void* swigGetSymbol(SwigSharedLibHandle hlib, string symbolName) {
|
|
return dlsym(hlib, swigToCString(symbolName));
|
|
}
|
|
|
|
string swigGetErrorStr() {
|
|
CCPTR err = dlerror();
|
|
if (err is null) {
|
|
return "Unknown Error";
|
|
}
|
|
return swigToDString(err);
|
|
}
|
|
} else version(Windows) {
|
|
alias ushort WORD;
|
|
alias uint DWORD;
|
|
alias CCPTR LPCSTR;
|
|
alias void* HMODULE;
|
|
alias void* HLOCAL;
|
|
alias int function() FARPROC;
|
|
struct VA_LIST {}
|
|
|
|
extern (Windows) {
|
|
HMODULE LoadLibraryA(LPCSTR);
|
|
FARPROC GetProcAddress(HMODULE, LPCSTR);
|
|
void FreeLibrary(HMODULE);
|
|
DWORD GetLastError();
|
|
DWORD FormatMessageA(DWORD, in void*, DWORD, DWORD, LPCSTR, DWORD, VA_LIST*);
|
|
HLOCAL LocalFree(HLOCAL);
|
|
}
|
|
|
|
DWORD MAKELANGID(WORD p, WORD s) {
|
|
return (((cast(WORD)s) << 10) | cast(WORD)p);
|
|
}
|
|
|
|
enum {
|
|
LANG_NEUTRAL = 0,
|
|
SUBLANG_DEFAULT = 1,
|
|
FORMAT_MESSAGE_ALLOCATE_BUFFER = 256,
|
|
FORMAT_MESSAGE_IGNORE_INSERTS = 512,
|
|
FORMAT_MESSAGE_FROM_SYSTEM = 4096
|
|
}
|
|
|
|
alias HMODULE SwigSharedLibHandle;
|
|
|
|
SwigSharedLibHandle swigLoadSharedLib(string libName) {
|
|
return LoadLibraryA(swigToCString(libName));
|
|
}
|
|
|
|
void swigUnloadSharedLib(SwigSharedLibHandle hlib) {
|
|
FreeLibrary(hlib);
|
|
}
|
|
|
|
void* swigGetSymbol(SwigSharedLibHandle hlib, string symbolName) {
|
|
return GetProcAddress(hlib, swigToCString(symbolName));
|
|
}
|
|
|
|
string swigGetErrorStr() {
|
|
DWORD errcode = GetLastError();
|
|
|
|
LPCSTR msgBuf;
|
|
DWORD i = FormatMessageA(
|
|
FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
|
FORMAT_MESSAGE_FROM_SYSTEM |
|
|
FORMAT_MESSAGE_IGNORE_INSERTS,
|
|
null,
|
|
errcode,
|
|
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
|
cast(LPCSTR)&msgBuf,
|
|
0,
|
|
null);
|
|
|
|
string text = swigToDString(msgBuf);
|
|
LocalFree(cast(HLOCAL)msgBuf);
|
|
|
|
if (i >= 2) {
|
|
i -= 2;
|
|
}
|
|
return text[0 .. i];
|
|
}
|
|
} else {
|
|
static assert(0, "Operating system not supported by the wrapper loading code.");
|
|
}
|
|
|
|
final class SwigSharedLib {
|
|
void load(string[] names) {
|
|
if (_hlib !is null) return;
|
|
|
|
string[] failedLibs;
|
|
string[] reasons;
|
|
|
|
foreach(n; names) {
|
|
_hlib = swigLoadSharedLib(n);
|
|
if (_hlib is null) {
|
|
failedLibs ~= n;
|
|
reasons ~= swigGetErrorStr();
|
|
continue;
|
|
}
|
|
_name = n;
|
|
break;
|
|
}
|
|
|
|
if (_hlib is null) {
|
|
throw new SwigSwigSharedLibLoadException(failedLibs, reasons);
|
|
}
|
|
}
|
|
|
|
void* loadSymbol(string symbolName, bool doThrow = true) {
|
|
void* sym = swigGetSymbol(_hlib, symbolName);
|
|
if(doThrow && (sym is null)) {
|
|
throw new SwigSymbolLoadException(_name, symbolName);
|
|
}
|
|
return sym;
|
|
}
|
|
|
|
void unload() {
|
|
if(_hlib !is null) {
|
|
swigUnloadSharedLib(_hlib);
|
|
_hlib = null;
|
|
}
|
|
}
|
|
|
|
private:
|
|
string _name;
|
|
SwigSharedLibHandle _hlib;
|
|
}
|
|
}
|
|
|
|
static this() {
|
|
string[] possibleFileNames;
|
|
version (Posix) {
|
|
version (OSX) {
|
|
possibleFileNames ~= ["lib$wraplibrary.dylib", "lib$wraplibrary.bundle"];
|
|
}
|
|
possibleFileNames ~= ["lib$wraplibrary.so"];
|
|
} else version (Windows) {
|
|
possibleFileNames ~= ["$wraplibrary.dll", "lib$wraplibrary.so"];
|
|
} else {
|
|
static assert(false, "Operating system not supported by the wrapper loading code.");
|
|
}
|
|
|
|
auto library = new SwigSharedLib;
|
|
library.load(possibleFileNames);
|
|
|
|
string bindCode(string functionPointer, string symbol) {
|
|
return functionPointer ~ " = cast(typeof(" ~ functionPointer ~
|
|
"))library.loadSymbol(`" ~ symbol ~ "`);";
|
|
}
|
|
|
|
//#if !defined(SWIG_D_NO_EXCEPTION_HELPER)
|
|
mixin(bindCode("swigRegisterExceptionCallbacks$module", "SWIGRegisterExceptionCallbacks_$module"));
|
|
//#endif // SWIG_D_NO_EXCEPTION_HELPER
|
|
//#if !defined(SWIG_D_NO_STRING_HELPER)
|
|
mixin(bindCode("swigRegisterStringCallback$module", "SWIGRegisterStringCallback_$module"));
|
|
//#endif // SWIG_D_NO_STRING_HELPER
|
|
$wrapperloaderbindcode
|
|
}
|
|
|
|
//#if !defined(SWIG_D_NO_EXCEPTION_HELPER)
|
|
extern(C) void function(
|
|
SwigExceptionCallback exceptionCallback,
|
|
SwigExceptionCallback illegalArgumentCallback,
|
|
SwigExceptionCallback illegalElementCallback,
|
|
SwigExceptionCallback ioCallback,
|
|
SwigExceptionCallback noSuchElementCallback) swigRegisterExceptionCallbacks$module;
|
|
//#endif // SWIG_D_NO_EXCEPTION_HELPER
|
|
|
|
//#if !defined(SWIG_D_NO_STRING_HELPER)
|
|
extern(C) void function(SwigStringCallback callback) swigRegisterStringCallback$module;
|
|
//#endif // SWIG_D_NO_STRING_HELPER
|
|
%}
|
|
|
|
%pragma(d) wrapperloaderbindcommand = %{
|
|
mixin(bindCode("$function", "$symbol"));%}
|