【问题标题】:AccessViolationException in PInvoke function callPInvoke 函数调用中的 AccessViolationException
【发布时间】:2013-01-02 05:33:15
【问题描述】:

我正在尝试为 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;
    }

有问题的参数是buffer,我之前尝试过用其他方式管理它,比如IntPtr bufferPtr然后通过Marshal.AllocHGlobal分配内存但我遇到了同样的错误:

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

如何正确调用该函数?

【问题讨论】:

  • 你没有指定 CallingConvention,很有可能是 Cdecl。
  • @HansPassant:谢谢。我刚刚尝试了所有可能的约定,但都没有改变这个错误(“尝试读取或写入受保护的内存。这通常表明其他内存已损坏。”)
  • 您需要开始调试 C 代码以缩小崩溃的原因。如果没有,请向所有者寻求帮助。
  • 附加原生调试器以查看发生了什么。

标签: c# memory pinvoke marshalling unmanaged


【解决方案1】:

适当的 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)]

【讨论】:

    【解决方案2】:

    尝试使用以下 PInvoke:

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

    【讨论】:

    • 第二个参数是PULONG。这是指向 uint 按值传递的点。因此,间接级别比您的答案少一级。
    猜你喜欢
    • 2013-10-18
    • 1970-01-01
    • 1970-01-01
    • 2011-02-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多