我试图在C#中编写代码以将位图传递给非托管c ++ DLL并返回POINT结构,但没有成功。
我在互联网上做了很多研究,但没有找到“Gotcha”文章或一段代码来帮我解决问题。
到目前为止,我能够提出的最好的是一个非托管的c ++ DLL,包含一个托管的c ++ dll,由我的C#app调用。在测试中,我可以传递简单类型,例如整数,并返回一个没有问题的整数。现在我遇到的问题是位图。
我试过传递一个HBITMAP(在c#中使用我的位图的GetHBitmap()函数)但是在编译“无法将参数1从'System :: IntPtr'转换为'HBITMAP'”和“Class1”时出错.FindImage(void *,void *)由于其保护级别而无法访问。
以下是我的一些代码:
主要应用程序:
class Program
{
[StructLayout(LayoutKind.Sequential)]
public struct POINT
{
public int X;
public int Y;
public POINT(int x, int y)
{
this.X = x;
this.Y = y;
}
public static implicit operator System.Drawing.Point(POINT p)
{
return new System.Drawing.Point(p.X, p.Y);
}
public static implicit operator POINT(System.Drawing.Point p)
{
return new POINT(p.X, p.Y);
}
}
static void Main(string[] args)
{
Image src = Image.FromFile("Pin.png");
Image tgt = Image.FromFile("screen.png");
Bitmap bsrc = new Bitmap(src);
Bitmap btgt = new Bitmap(tgt);
IntPtr bs = bsrc.GetHbitmap();
IntPtr bt = btgt.GetHbitmap();
POINT p = Class1.FindImage(bs, bt);
}
}
ImportWrap.h:
namespace ImportWrap {
public ref class Class1
{
public:
static POINT FindImage(IntPtr source, IntPtr target);
};
}
ImportWrap.cpp:
static POINT FindImage(IntPtr source, IntPtr target)
{
return ImgFuncs::MyImgFuncs::FindImage(source, target);
}
ImgFuncs.h
typedef long LONG;
typedef void *PVOID;
typedef PVOID HANDLE;
typedef HANDLE HBITMAP;
typedef struct tagPOINT {
LONG x;
LONG y;
} POINT, *PPOINT;
namespace ImgFuncs
{
class MyImgFuncs
{
public:
static __declspec(dllexport) POINT FindImage(HBITMAP source, HBITMAP target);
};
}
ImgFuncs.cpp
namespace ImgFuncs
{
POINT MyImgFuncs::FindImage(HBITMAP source, HBITMAP target)
{
POINT p;
p.x = 1;
p.y = 2;
return p;
}
}
我做错了什么,或者我用我的方法完全离开地图? 我会很乐意接受有关正确编码我想要做的事情的正确方法的任何建议。 我有一些C ++代码用于在另一个图像中查找工作得非常快的图像。不幸的是,即使在c#中使用lockbits,也不够快。所以我想利用c ++代码进行图像搜索。
我相信我会遇到进一步的障碍,但如果我能够克服这个绊脚石,我或许可以处理它。如您所见,我的C ++知识是有限的。
答案 0 :(得分:3)
您不能使用本机结构类型作为返回值,C#无法处理它们。从IntPtr到HBITMAP的转换需要双重演员。像这样:
static System::Drawing::Point FindImage(IntPtr source, IntPtr target)
{
POINT retval = ImgFuncs::MyImgFuncs::FindImage((HBITMAP)(void*)source, (HBITMAP)(void*)target);
return System::Drawing::Point(retval.X, retval.Y);
}
向System.Drawing添加程序集引用。您可能还想考虑传递Bitmap ^而不是IntPtr,以使其更易于使用。
答案 1 :(得分:1)
您可以完全跳过托管C ++包装器,只需通过P / Invoke从C#调用非托管DLL。把这样的东西放在你的C#类
中[DllImport("YourUnamangedDll.dll")]
private static extern POINT FindImage(IntPtr source, IntPtr target);
我没有对此进行测试,因此您可能需要根据需要进行调整,但这是一般的想法。