1

次の定義を持つ関数を含む、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 を渡す適切な方法は何ですか?

4

1 に答える 1

1

単に属性を使用するだけLoadLibraryGetProcAddressFreeLibrary複雑さをすべて取り除くことができると思います。DllImportとはいえ、なぜあなたがこの道を選んだのか、具体的な理由についてはわかっていないと言えます。

ref double doubleArgとにかく、 PDouble を渡すために宣言に含めることができます。ここは必要ないはずIntPtrです。

于 2012-07-12T12:09:14.533 に答える