C# からアンマネージドな DLL を使用するには DllImportAttribute を用いた方法が多いのですが,動的に読み込みたい場合もあります。アンマネージド DLL を遅延バインディングするクラスは .NET Framework に用意されていないと思いますので,自前で用意してやる必要があります。
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | 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)))
の行がものすごく浮いている気がします。