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 异常。

将 PDouble 传递到非托管 Delphi DLL 文件的正确方法是什么?

4

1 回答 1

1

我认为您可以通过简单地使用属性来消除所有LoadLibrary,GetProcAddressFreeLibrary复杂性。DllImport不过,我可以说我不知道​​你为什么选择这条路的任何具体原因。

无论如何,您可以简单地ref double doubleArg在声明中包含通过 PDouble。这里应该没有必要IntPtr

于 2012-07-12T12:09:14.533 回答