2

我正在尝试为 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分配内存,但我得到了同样的错误:

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

如何正确调用该函数?

4

2 回答 2

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)]
于 2013-01-18T20:47:59.597 回答
0

尝试使用以下 PInvoke:

[DllImport(DRIVER_FILENAME)]
private static extern Int32 GetData
(
    [In] IntPtr handle,
    [Out] out IntPtr buffer,
    [In] UInt32 size
);
于 2013-01-18T18:17:53.337 回答