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))) の行がものすごく浮いている気がします。