次の定義を持つ関数を含む、Delphi で記述されたアンマネージ DLL ファイルがあります。
function F(tgran: integer; inputs: PDouble; goutp, outputs, toutp: PDouble): integer; stdcall; external 'mydll.dll';
私はそれを消費するのに役立つはずの C# でアダプターを作成しました。
[UnmanagedFunctionPointer(APIAdapter.Convention)]
public delegate int FDelegate(int tgran, IntPtr inputs, IntPtr goutp, IntPtr outputs, IntPtr toutp);
public class APIAdapter : IDisposable
{
public const string DllName = "mydll.dll";
public const CallingConvention Convention = CallingConvention.StdCall;
public FDelegate F;
[DllImport("kernel32")]
private static extern IntPtr LoadLibrary(string lpLibFileName);
[DllImport("kernel32")]
private static extern bool FreeLibrary(IntPtr hModule);
[DllImport("kernel32.dll")]
private static extern IntPtr GetProcAddress(IntPtr hModule, String procname);
private IntPtr _dllHandle;
public APIAdapter()
{
_dllHandle = LoadLibrary(DllName);
F = (FDelegate)GetFunction<CalcCavSpDelegate>("F");
}
private Delegate GetFunction<T>(string procName)
{
IntPtr procAddress = GetProcAddress(_dllHandle, procName);
return Marshal.GetDelegateForFunctionPointer(procAddress, typeof(T));
}
~APIAdapter()
{
Dispose(false);
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
private void Dispose(bool disposing)
{
if (disposing)
{
}
while (FreeLibrary(_dllHandle))
{
}
}
}
使用方法は非常に簡単です。
using(var api = new APIAdapter())
{
// Call API functions
}
問題は、DLL ファイル内で発生する AccessViolationException です。
PDouble 変数を として渡そうとしましたdouble[], double* (unsafe code), IntPtr
。どの方法を選んでも同じ話です。配列のインデックス付けでエラーを除外するために、渡される配列のサイズを大幅に大きくしようとしました-AccessViolation例外が再び発生しました。
アンマネージ Delphi DLL ファイルに PDouble を渡す適切な方法は何ですか?