如何使用PInvoke传递图像

时间:2012-01-16 11:03:21

标签: c# pinvoke

我有一个C DLL,它对图像进行一些处理并返回结果。所以我试图从.NET端传递一个图像,但是现在我被卡住了,我不确定这是关于类型,编组的复杂性还是语法。由于我是菜鸟,所以可能都是三个。

我可以调用DLL中的其他函数,因此至少有一些基础已经到位。例如,当我打电话时:

IntPtr versionIntPtr = GetDLLVersionNumber();
string version = Marshal.PtrToStringAnsi(versionIntPtr);
Console.WriteLine("DLL version number reported as: " + version);

这非常正常,将当前版本的DLL打印到控制台。

当我查看使用相同功能的C代码示例时,它似乎使用如下函数:

unsigned char* ExtractImageInfo(const char* pixels, size_t width, size_t height)

(我还有一个头文件,其中提到了相同的功能如下:

... ExtractImageInformation(struct ImageData image, void* imageInformation);

但我真的不知道这意味着什么。)

所以我尝试使用这个函数如下:

首先,我指定DLL的接口:

[DllImport("C:\\MyDLL", EntryPoint = "ExtractImageInfo", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr ExtractImageInfo(IntPtr image, UInt32 imageWidth, UInt32 imageHeight); 

然后,我得到一个正确类型的图像并得到它的尺寸:

Bitmap bitmap1 = (Bitmap)Image.FromFile("C:\\Images\\myImage.bmp");
UInt32 _imageWidth = Convert.ToUInt32(bitmap1.Width);
UInt32 _imageHeight = Convert.ToUInt32(bitmap1.Height);

然后我得到一个指向图像的指针(因为我认为这是我需要传递的):

IntPtr bitmap1Ptr = bitmap1.GetHbitmap();

然后我调用函数......

IntPtr myProcessedImage;
myProcessedImage = ExtractImageInfo(bitmap1Ptr, _imageWidth, _imageHeight);

但它不起作用 - 我没有得到指向我处理过的数据的指针。我想知道的很大一部分是我是否以正确的方式传递图像,以及我的本机函数接口的语法是否正确。我想可能两者的答案都可能是NO!

我只有几天阅读和试验PInvoke,所以如果有人能指出我的方式错误,我会永远感激: - )

1 个答案:

答案 0 :(得分:3)

 unsigned char* ExtractImageInfo(const char* pixels, size_t width, size_t height)

参数的名称强烈暗示它需要一个指向原始像素数据的指针。您可以从Bitmap.LockBits(),BitmapData.Scan0属性中获取一个。在函数返回之前不要调用UnlockBits()。

该函数的返回类型是一个重要的内存管理问题。无论返回什么缓冲区指针几乎肯定都要发布。您无法从托管代码执行此操作,您无权访问此C代码使用的分配器来调用正确版本的free()。调用此函数一百万次,并仔细检查您是否没有失控内存泄漏。如果你这样做,你就无法对它进行排序,需要一个C ++ / CLI包装器,尽管它正常工作的几率也相当渺茫。这是一个设计糟糕的功能,很难从任何代码中使用,包括C。