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

发布于 2024-09-13 05:11:13 字数 825 浏览 7 评论 0原文

我正在尝试调用包含在 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 文件中......有人有什么想法吗?

I'm trying to call the following C++ function that's wrapped up into a DLL:

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

My import statement looks like the following:

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

And my call routine looks like the following:

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);

However, I keep getting a runtime error:

A first chance exception of type System.AccessViolationException occurred in xxx.dll
Attempted to read or write protected memory. This is often an indication that other memory is corrupt.

I'm just wondering if the fault lies in the way I'm marshaling my data or in my imported DLL file... anyone have any ideas?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

空城之時有危險 2024-09-20 05:11:13

发生这种情况的原因可能是该方法的调用约定与编组器猜测的不同。您可以在 DllImport 属性中指定约定。

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

This is likely occurring because the calling convention of the method is not as the marshaller is guessing it to be. You can specify the convention in the DllImport attribute.

You don't need the 'unsafe' keyword in the C# declaration here as it's not 'unsafe' code. Perhaps you were trying it with a 'fixed' pointer at one point and forgot to remove the unsafe keyword before posting?

习惯成性 2024-09-20 05:11:13

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

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

not sure if this is your problem, but in general C++ pointers map to IntPtr. so try modifying your import statement to this:

[DllImport("mex_rectify_image.dll")]
unsafe public static extern IntPtr rectifyImage(
IntPtr pData, int rows, int columns);
小…楫夜泊 2024-09-20 05:11:13

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;
}

unsigned char *pimg can't be marshalled to byte[] automatically.

In order to pass the byte[] imageData you need to marshal it manually to IntPtr and pass said IntPtr to rectifyImage.

This is the recommended pattern for implementing such marshaling:

[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;
}
病女 2024-09-20 05:11:13

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

rectifyImage Is looking for a ponter to a the 1st byte in a block for data you are sending in the block. Try imageData[0]

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文