1 
2 module llvm.util.shlib;
3 
4 private
5 {
6 	import std.string : toStringz, fromStringz;
7 	import std.conv : to;
8 }
9 
10 final class SharedLibLoadException : Exception
11 {
12 	@safe pure nothrow
13 	this(string msg)
14 	{
15 		super(msg);
16 	}
17 }
18 
19 version(Posix)
20 {
21 	private import core.sys.posix.dlfcn;
22 
23 	alias void* SharedLibHandle;
24 
25 	version(OSX)
26 	{
27 		string libPrefix = "lib";
28 		string libSuffix = "dylib";
29 	}
30 	else
31 	{
32 		string libPrefix = "lib";
33 		string libSuffix = "so";
34 	}
35 
36 	pragma(lib, "dl");
37 }
38 else version(Windows)
39 {
40 	private import core.sys.windows.windows;
41 	private import std.path : dirName;
42 
43 	alias HMODULE SharedLibHandle;
44 
45 	string libPrefix = "";
46 	string libSuffix = "dll";
47 } else {
48 	static assert(false, "Shared libraries unimplemented for this system.");
49 }
50 
51 class SharedLib
52 {
53 	private SharedLibHandle handle;
54 	private string libName;
55 	
56 	public this(string libName)
57 	{
58 		this.libName = libName;
59 	}
60 
61 	public void load()
62 	{
63 		return loadFile(libName);
64 	}
65 
66 	private void loadFile(string file)
67 	{
68 		version(Posix)
69 		{
70 			if((handle = dlopen(file.toStringz(), RTLD_NOW)) is null)
71 			{
72 				throw new SharedLibLoadException("Failed to load library "~file~": "~dlerror().fromStringz().idup);
73 			}
74 		}
75 		else version(Windows)
76 		{
77 			if((handle = LoadLibraryA(file.toStringz())) is null)
78 			{
79 				LPCSTR error;
80 				DWORD tchar_length = FormatMessageA(
81 					FORMAT_MESSAGE_ALLOCATE_BUFFER |
82 					FORMAT_MESSAGE_FROM_SYSTEM |
83 					FORMAT_MESSAGE_IGNORE_INSERTS,
84 					null,
85 					GetLastError(),
86 					MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
87 					cast(char*) &error,
88 					0,
89 					null);
90 				scope(exit) LocalFree(cast(HLOCAL) error);
91 				
92 				throw new SharedLibLoadException("Failed to load library "~file~": "~error[0..tchar_length]);
93 			}
94 		}
95 	}
96 
97 	public void unload()
98 	{
99 		version(Posix)
100 		{
101 			if(handle !is null)
102 			{
103 				dlclose(handle);
104 			}
105 		}
106 		else
107 		{
108 			if(handle !is null)
109 			{
110 				FreeLibrary(handle);
111 			}
112 		}
113 	}
114 
115 	public T loadSymbol(T)(string symbol)
116 	{
117 		version(Posix)
118 		{
119 			return cast(T) dlsym(handle, symbol.toStringz());
120 		}
121 		else
122 		{
123 			return cast(T) GetProcAddress(handle, symbol.toStringz());
124 		}
125 	}
126 }