我正在尝试调用以下封装在 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 文件中......有人有什么想法吗?
这很可能发生,因为该方法的调用约定与编组器猜测的不同。您可以在 DllImport 属性中指定约定。
此处的 C# 声明中不需要“不安全”关键字,因为它不是“不安全”代码。也许您曾在某一时刻尝试使用“固定”指针,但忘记在发布之前删除不安全的关键字?
不确定这是否是您的问题,但一般来说,C++ 指针映射到 IntPtr。所以尝试将您的导入语句修改为:
[DllImport("mex_rectify_image.dll")]
unsafe public static extern IntPtr rectifyImage(
IntPtr pData, int rows, int columns);
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;
}
rectifyImage 正在寻找块中第一个字节的标记,以获取您在块中发送的数据。尝试 imageData[0]