1 /* 2 __ 3 / _| 4 __ _ _ _ _ __ ___ _ __ __ _ | |_ ___ ___ ___ 5 / _` | | | | '__/ _ \| '__/ _` | | _/ _ \/ __/ __| 6 | (_| | |_| | | | (_) | | | (_| | | || (_) \__ \__ \ 7 \__,_|\__,_|_| \___/|_| \__,_| |_| \___/|___/___/ 8 9 Copyright © 2013-2016, Mike Parker. 10 Copyright © 2016, 渡世白玉. 11 Copyright © 2018, Michael D. Parker 12 Copyright © 2018-2019, Aurora Free Open Source Software. 13 14 This file is part of the Aurora Free Open Source Software. This 15 organization promote free and open source software that you can 16 redistribute and/or modify under the terms of the GNU Lesser General 17 Public License Version 3 as published by the Free Software Foundation or 18 (at your option) any later version approved by the Aurora Free Open Source 19 Software Organization. The license is available in the package root path 20 as 'LICENSE' file. Please review the following information to ensure the 21 GNU Lesser General Public License version 3 requirements will be met: 22 https://www.gnu.org/licenses/lgpl.html . 23 24 Alternatively, this file may be used under the terms of the GNU General 25 Public License version 3 or later as published by the Free Software 26 Foundation. Please review the following information to ensure the GNU 27 General Public License requirements will be met: 28 https://www.gnu.org/licenses/gpl-3.0.html. 29 30 NOTE: All products, services or anything associated to trademarks and 31 service marks used or referenced on this file are the property of their 32 respective companies/owners or its subsidiaries. Other names and brands 33 may be claimed as the property of others. 34 35 For more info about intellectual property visit: aurorafoss.org or 36 directly send an email to: contact (at) aurorafoss.org . 37 38 This file is an improvement of an existing code, part of DerelictUtil 39 from DerelictOrg. Check it out at derelictorg.github.io . 40 41 This file is an improvement of an existing code, developed by 渡世白玉 42 and available on github at https://github.com/huntlabs/DerelictUtil . 43 44 This file is an improvement of an existing code, part of bindbc-loader 45 from BindBC. Check it out at github.com/BindBC/bindbc-loader . 46 */ 47 48 module riverd.builder; 49 50 import std.traits; 51 52 /** Dynamic Library Loader Builder 53 * This template combined with a mixin, 54 * build automatically a dynamic loader for a specific library. 55 * @param handle_name handle name, normally the library name 56 * @param libs possible libraries names array 57 * @param T alias to dynfun specific library module 58 * @param required strictly require, otherwise throw an exception 59 */ 60 template DylibLoaderBuilder(string handle_name, string[] libs, alias T, bool required = false) 61 { 62 string _buildLoader(string handle_name, string[] libs, alias T, bool required = false)() 63 { 64 static if(required) 65 enum dthrow = "true"; 66 else 67 enum dthrow = "false"; 68 69 string ret = "\n"; 70 71 import std.string : toLower; 72 73 version(D_BetterC) 74 { 75 // implementation of dynamic loader for -betterC 76 import std.array : join; 77 ret ~= "void* dylib_load_" ~ toLower(handle_name) ~ "() { void* handle;"; 78 foreach(string lib; libs) 79 ret ~= "if(handle is null) handle = dylib_load(\"" ~ lib ~ "\");\n"; 80 ret ~= "if(handle is null) return null;\n\n"; 81 } 82 else { 83 // create dylib_load function for garbage collected loader 84 ret ~= "pragma(inline, true) void* dylib_load_" ~ toLower(handle_name) 85 ~ "() { return cast(void*)(new " ~ handle_name ~ "DylibLoader()); }\n class " 86 ~ handle_name ~ "DylibLoader : DylibLoader {\nthis() { super("; 87 88 string tmp = "["; 89 foreach(string t; libs) 90 tmp~="\""~t~"\","; 91 tmp= tmp[0 .. $-1]; 92 tmp~="]"; 93 94 ret ~= tmp ~ "); }\noverride void loadSymbols() {\n"; 95 } 96 97 foreach(mem; __traits(derivedMembers, T)) 98 { 99 static if( isFunctionPointer!(__traits(getMember, T, mem))) 100 { 101 version(D_BetterC) ret ~= "\tdylib_bindSymbol(handle,cast(void**)&" ~ mem ~ ", \"" ~ mem ~ "\");\n"; 102 else ret ~= "\tbindFunc(" ~ mem ~ ", \"" ~ mem ~ "\", " ~ dthrow ~ ");\n"; 103 } 104 } 105 version(D_BetterC) 106 { 107 ret ~= "return handle; }"; 108 } 109 else { 110 ret ~= "}}"; 111 } 112 return ret; 113 } 114 115 enum DylibLoaderBuilder = _buildLoader!(handle_name, libs, T, required)(); 116 } 117 118 /** Dynamic Library Type Builder 119 * This template combined with a mixin, 120 * build automatically the types needed by the dynamic loader. 121 * @param T alias to dynfun specific library module 122 */ 123 template DylibTypeBuilder(alias T) 124 { 125 string _buildTypes(alias T)() 126 { 127 string ret; 128 foreach(func; __traits(derivedMembers, T)) 129 { 130 alias ftype = __traits(getMember, T, func); 131 static if(isFunction!(ftype)) 132 ret ~= "alias da_" ~ func ~ " = "~ ReturnType!(ftype).stringof ~ " function" ~ Parameters!(ftype).stringof ~ ";\n"; 133 } 134 135 return ret; 136 } 137 138 enum DylibTypeBuilder = _buildTypes!(T)(); 139 }