public void loadLibrary(String path, String dll_name, string resource_name, bool make_unique_dll_name) { lock (_sync_object) { DllData data = null; if (_loaded_dlls.TryGetValue(dll_name, out data)) { // Library has already been loaded if (data.lib_path != path) { throw new Exception(String.Format("Library {0} has already been loaded by different path {1}", dll_name, data.lib_path)); } return; } data = new DllData(); data.lib_path = path; data.file_name = _getPathToBinary(path, dll_name, resource_name, Assembly.GetCallingAssembly(), make_unique_dll_name); data.file_name = data.file_name.Replace('/', '\\'); data.handle = LibraryLoader.LoadLibrary(data.file_name); if (data.handle == IntPtr.Zero) { throw new Exception("Cannot load library " + dll_name + " from the temporary file " + data.file_name.Replace('\\', '/') + ": " + LibraryLoader.GetLastError() ); } _loaded_dlls.Add(dll_name, data); _dll_handles.Add(data); } }
// Creates implementation of a given interface for wrapping function the specified DLL WrappedInterface createInterface <IT>(string dll_name) where IT : class { WrappedInterface result = new WrappedInterface(); Type itype = typeof(IT); AppDomain cd = System.Threading.Thread.GetDomain(); AssemblyName an = new AssemblyName(); an.Name = itype.Name + "_" + dll_name.Replace('.', '_'); AssemblyBuilder ab = cd.DefineDynamicAssembly(an, AssemblyBuilderAccess.Run); ModuleBuilder mb = ab.DefineDynamicModule(an.Name, false); TypeBuilder tb = mb.DefineType(an.Name, TypeAttributes.Class | TypeAttributes.Public); tb.AddInterfaceImplementation(itype); IntPtr dll_handle = _loaded_dlls[dll_name].handle; Dictionary <List <Type>, Type> signature_to_name = new Dictionary <List <Type>, Type>(new TypeListComparer()); // Set delegate references foreach (MethodInfo m in itype.GetMethods()) { ParameterInfo[] parameters = m.GetParameters(); Type[] arg_types = new Type[parameters.Length]; for (int i = 0; i < parameters.Length; i++) { arg_types[i] = parameters[i].ParameterType; } Type delegate_ret_type = m.ReturnType; if (delegate_ret_type == typeof(String)) { delegate_ret_type = typeof(sbyte *); } List <Type> signature = new List <Type>(); signature.Add(delegate_ret_type); signature.AddRange(arg_types); Type call_delegate = null; if (!signature_to_name.TryGetValue(signature, out call_delegate)) { // Check if type was already created string delegate_type_name = String.Format("delegate_{0}", signature_to_name.Count); call_delegate = createDelegateType(delegate_type_name, mb, delegate_ret_type, arg_types); signature_to_name.Add(signature, call_delegate); } string delegate_field_name = m.Name + "_ptr"; FieldBuilder delegate_field = tb.DefineField(delegate_field_name, typeof(Delegate), FieldAttributes.Private); IntPtr proc = LibraryLoader.GetProcAddress(dll_handle, m.Name); if (proc == IntPtr.Zero) { throw new Exception(String.Format("Cannot find procedure {0} in the library {1}", m.Name, dll_name)); } Delegate proc_delegate = Marshal.GetDelegateForFunctionPointer(proc, call_delegate); result.delegates.Add(delegate_field_name, proc_delegate); MethodBuilder meth = tb.DefineMethod(m.Name, MethodAttributes.Public | MethodAttributes.Virtual, m.ReturnType, arg_types); ILGenerator il = meth.GetILGenerator(); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldfld, delegate_field); for (int i = 1; i < arg_types.Length + 1; i++) { il.Emit(OpCodes.Ldarg, i); } MethodInfo infoMethod = proc_delegate.GetType().GetMethod("Invoke", arg_types); il.EmitCall(OpCodes.Callvirt, infoMethod, null); // Automatically convert sbyte* to String if (m.ReturnType == typeof(String)) { Type str_type = typeof(String); ConstructorInfo ci = str_type.GetConstructor(new Type[] { typeof(sbyte *) }); il.Emit(OpCodes.Newobj, ci); } il.Emit(OpCodes.Ret); tb.DefineMethodOverride(meth, m); } // ab.Save(an.Name + ".dll"); Type impl_class = tb.CreateType(); IT impl = (IT)Activator.CreateInstance(impl_class); // Set references to the delegates foreach (string field_name in result.delegates.Keys) { impl_class.GetField(field_name, BindingFlags.Instance | BindingFlags.NonPublic) .SetValue(impl, result.delegates[field_name]); } result.instance = impl; return(result); }
public void loadLibrary(String path, String dll_name, string resource_name, bool make_unique_dll_name) { lock (_sync_object) { DllData data = null; if (_loaded_dlls.TryGetValue(dll_name, out data)) { // Library has already been loaded if (data.lib_path != path) { throw new Exception(String.Format("Library {0} has already been loaded by different path {1}", dll_name, data.lib_path)); } return; } String subprefix = null; switch (Environment.OSVersion.Platform) { case PlatformID.Win32NT: subprefix = (IntPtr.Size == 8) ? "Win/x64/" : "Win/x86/"; break; case PlatformID.Unix: if (isMac()) { subprefix = "Mac/10.7/"; } else { subprefix = (IntPtr.Size == 8) ? "Linux/x64/" : "Linux/x86/"; } break; default: throw new PlatformNotSupportedException(String.Format( "Unsupported platform: {0}", Environment.OSVersion.Platform ) ); } data = new DllData(); data.lib_path = path; data.file_name = _getPathToBinary(path, subprefix + dll_name, resource_name, Assembly.GetCallingAssembly(), make_unique_dll_name); data.file_name = data.file_name.Replace('/', '\\'); data.handle = LibraryLoader.LoadLibrary(data.file_name); if (data.handle == IntPtr.Zero) { throw new Exception("Cannot load library " + dll_name + " from the temporary file " + data.file_name.Replace('\\', '/') + ": " + LibraryLoader.GetLastError() ); } _loaded_dlls.Add(dll_name, data); _dll_handles.Add(data); } }