3

我试图在 C# 中编写代码以将位图传递给非托管 c++ DLL 并返回 POINT 结构,但没有成功。

我在互联网上做了很多研究,但没有找到“Gotcha”文章或一段代码来帮助我解决我的问题。

到目前为止,我能想到的最好的方法是一个非托管 c++ DLL,用托管 c++ dll 包装,由我的 C# 应用程序调用。在测试中,我可以传递简单的类型,例如整数并毫无问题地返回整数。现在对于我遇到的问题,位图。

我尝试传递 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);
    }
}

进口包装.h:

namespace ImportWrap {

public ref class Class1
{
public:
    static POINT FindImage(IntPtr source, IntPtr target);
};
}

导入包装.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++ 知识有限。

4

2 回答 2

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 以使其更易于使用。

于 2012-01-14T12:28:30.710 回答
1

您可以完全跳过托管 C++ 包装器,只需通过 P/Invoke 从 C# 调用非托管 DLL。把这样的东西放在你的 C# 类中

[DllImport("YourUnamangedDll.dll")]
private static extern POINT FindImage(IntPtr source, IntPtr target);

我没有对此进行测试,因此您可能需要根据需要对其进行调整,但这是一般的想法。

于 2012-01-14T09:04:51.473 回答