如何在 C# 中编组字节数组?

问题描述 投票:0回答:4

我正在尝试调用以下封装在 DLL 中的 C++ 函数:

unsigned char * rectifyImage(unsigned char *pimg, int rows, int cols)

我的导入语句如下所示:

[DllImport("mex_rectify_image.dll")]
unsafe public static extern IntPtr rectifyImage(
byte[] data, int rows, int columns);

我的通话例程如下所示:

byte[] imageData = new byte[img.Height * img.Width * 3];
// ... populate imageData
IntPtr rectifiedImagePtr = rectifyImage(imageData, img.Height, img.Width);
Byte[] rectifiedImage = new Byte[img.Width * img.Height * 3];
Marshal.Copy(rectifiedImagePtr, rectifiedImage, 0, 3 * img.Width * img.Height);

但是,我不断收到运行时错误:

xxx.dll 中发生了

System.AccessViolationException
类型的第一次机会异常 尝试读取或写入受保护的内存。这通常表明其他内存已损坏。

我只是想知道问题是否出在我整理数据的方式或我导入的 DLL 文件中......有人有什么想法吗?

c# marshalling byte
4个回答
1
投票

这很可能发生,因为该方法的调用约定与编组器猜测的不同。您可以在 DllImport 属性中指定约定。

此处的 C# 声明中不需要“不安全”关键字,因为它不是“不安全”代码。也许您曾在某一时刻尝试使用“固定”指针,但忘记在发布之前删除不安全的关键字?


1
投票

不确定这是否是您的问题,但一般来说,C++ 指针映射到 IntPtr。所以尝试将您的导入语句修改为:

[DllImport("mex_rectify_image.dll")]
unsafe public static extern IntPtr rectifyImage(
IntPtr pData, int rows, int columns);

0
投票

unsigned char *pimg
无法自动编组到
byte[]

为了传递

byte[] imageData
,您需要手动将其编组到
IntPtr
并将所述
IntPtr
传递到
rectifyImage

这是实现此类封送的推荐模式:

[DllImport("mex_rectify_image.dll", EntryPoint = "rectifyImage")]
private static extern IntPtr rectifyImageInternal(IntPtr data, int rows, int cols);

public static byte[] rectifyImage(byte[] data, int rows, int cols)
{
    IntPtr dataPtr = IntPtr.Zero;
    byte[] result = new byte[data.Length]; // assumes result is the same size as data
    
    try {
        dataPtr = Marshal.AllocHGlobal(data.Length);
        
        Marshal.Copy(data, 0, dataPtr, data.Length);
        
        IntPtr resultPtr = rectifyImageInternal(dataPtr, rows, cols);
        
        Marshal.Copy(resultPtr, result, 0, result.Length);
        
        // TODO:
        //  - Is resultPtr perhaps the same as dataPtr (in-place transform on source image)?
        //    If not:
        //      - Who is responsible for freeing resultPtr?
        //      - What allocation method was used for resultPtr (global/cotask/etc)?
        //  - Error handling
    } finally {
        Marshal.FreeHGlobal(dataPtr);
    }
    
    return Result;
}

-1
投票

rectifyImage 正在寻找块中第一个字节的标记,以获取您在块中发送的数据。尝试 imageData[0]

© www.soinside.com 2019 - 2024. All rights reserved.