如何使用PInvoke传递图像

本文关键字:图像 PInvoke 何使用 | 更新日期: 2023-09-27 18:20:20

我有一个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);

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

我只读了几天书,并尝试了PInvoke,所以如果有人能向我指出我的错误,我将永远感激:-)

如何使用PInvoke传递图像

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

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

函数的返回类型是一个重要的内存管理问题。几乎可以肯定的是,无论返回什么缓冲区指针,都必须被释放。你不能从托管代码中这样做,你没有访问这个C代码用来调用free()正确版本的分配器的权限。调用此函数一百万次,然后再次检查是否存在失控的内存泄漏。如果你这样做了,那么你就无法确定它,需要一个C++/CLI包装器,尽管它正确工作的可能性也很小。这是一个设计糟糕的函数,很难从任何代码中使用,包括C.