PInvoke函数调用中的AccessViolationException

时间:2013-01-18 13:35:29

标签: c# memory pinvoke marshalling unmanaged

我正在尝试为C库编写一个包装器,但我真的在努力解决这个错误。

我尝试了很多方法,其中之一是:

    [DllImport(DRIVER_FILENAME)]
    [return: MarshalAs(UnmanagedType.U4)]
    private static extern uint GetData(IntPtr handle,
        [MarshalAs(UnmanagedType.LPArray), In()] int[] buffer,
        [MarshalAs(UnmanagedType.U4)] uint size);

这是库文档中的函数 GetData

LONG GetData( 
  IN HANDLE Handle,
  OUT PULONG Buffer, 
  IN ULONG Size
); 

函数在缓冲区中返回连续数据(大约16KB / s),其大小以字节为单位。 缓冲区 int [16384] 。我的代码如下所示:

public static uint GetLibData(IntPtr handle, int[] buffer, uint size)
    {
        size *= 4;            
        uint sizeRead = GetData(handle, buffer, size);

        sizeRead /= 4;

        return sizeRead;
    }

有问题的参数是缓冲区,我尝试以其他方式管理它,例如 IntPtr bufferPtr ,然后通过 Marshal.AllocHGlobal 分配内存但我得到了同样的错误:

  

尝试读取或写入受保护的内存。这通常是一个   表明其他内存已损坏。

如何正确调用此功能?

2 个答案:

答案 0 :(得分:0)

尝试使用以下PInvoke:

[DllImport(DRIVER_FILENAME)]
private static extern Int32 GetData
(
    [In] IntPtr handle,
    [Out] out IntPtr buffer,
    [In] UInt32 size
);

答案 1 :(得分:0)

适当的p / invoke声明是

[DllImport(DRIVER_FILENAME)]
private static extern uint GetData(
    IntPtr handle,
    [Out] uint[] buffer,
    uint size
);

在调用函数之前,您有责任分配缓冲区:

uint[] buffer = new uint[16384];
uint bufferSize = buffer.Length*Marshal.SizeOf(typeof(uint));
uint sizeRead = GetData(handle, buffer, bufferSize);
uint lenRead = sizeRead/Marshal.SizeOf(typeof(uint));

唯一不是100%明确的是调用约定。我猜这个库使用cdecl,这意味着你的DllImport应该是

[DllImport(DRIVER_FILENAME, CallingConvention=CallingConvention.Cdecl)]