C# からアンマネージドな DLL を使用するには DllImportAttribute を用いた方法が多いのですが,動的に読み込みたい場合もあります。アンマネージド DLL を遅延バインディングするクラスは .NET Framework に用意されていないと思いますので,自前で用意してやる必要があります。
public class LateBoundUnmanagedDll : SafeHandle { public override bool IsInvalid { get { return IsClosed || this.handle == IntPtr.Zero; } } public LateBoundUnmanagedDll(string dllName) : base(IntPtr.Zero, true) { IntPtr handle = LoadLibrary(dllName); SetHandle(handle); } protected override bool ReleaseHandle() { return FreeLibrary(this.handle); } public TDelegate GetFunction<TDelegate>(string entryPoint) where TDelegate : class { if (!typeof(TDelegate).IsSubclassOf(typeof(Delegate))) { throw new ArgumentException(); } IntPtr function = GetProcAddress(this.handle, entryPoint); return Marshal.GetDelegateForFunctionPointer(function, typeof(TDelegate)) as TDelegate; } [DllImport("kernel32.dll")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool SetDllDirectory([MarshalAs(UnmanagedType.LPStr)] string lpPathName); [DllImport("kernel32.dll")] private static extern IntPtr LoadLibrary([MarshalAs(UnmanagedType.LPStr)] string lpFileName); [DllImport("kernel32.dll")] [return: MarshalAs(UnmanagedType.Bool)] private static extern bool FreeLibrary(IntPtr hModule); [DllImport("kernel32.dll")] private static extern IntPtr GetProcAddress(IntPtr hModule, [MarshalAs(UnmanagedType.LPStr)] string lpProcName); }
GetFunction
で関数ポインタをデリゲートに変換してやります。ジェネリックの制約に Delegate
クラスが利用できないのが残念です。 if(!typeof(TDelegate).IsSubclassOf(typeof(Delegate)))
の行がものすごく浮いている気がします。