3

I am trying without success to write code in C# to pass a bitmap to an unmanaged c++ DLL and return a POINT structure.

I have done a lot of research on the internet, but have not found the "Gotcha" article or piece of code to help me resolve my issue.

The best I have been able to come up with so far is an unmanaged c++ DLL, wrapped with a managed c++ dll, called by my C# app. In testing that, I can pass simple types, such as an integer and return an integer with no problem. Now for the issue I am having, the bitmap.

I have tried passing an HBITMAP (using the GetHBitmap() function of my bitmap in c#), but I get errors during compile of "cannot convert parameter 1 from 'System::IntPtr' to 'HBITMAP'" and "Class1.FindImage(void *, void *) is inaccessible due to it's protection level".

Here is some of my code:

Main App:

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;
}
}

What am I doing wrong, or am I going completely off the map with my approach? I would GLADLY entertain any suggestions regarding the correct way to code what I am trying to do. I have some C++ code that is used to find an image within another image that works quite fast. Unfortunately, even using lockbits in c#, it's not fast enough. So I would like to make use of the c++ code for the image search.

I am sure I will run into further snags, but might be able to handle it if I can get past this stumbling block. As you can see, my C++ knowledge is limited.

1
  • The function declared in ImportWrap.cpp is incorrect. You can't implicitly convert an IntPtr (which is passed in to the function) to an HBITMAP type (which the function tries to pass on to the other function it calls). Commented Jan 14, 2012 at 12:25

2 Answers 2

3

You cannot use native struct types as a return value, C# can't handle them. Casting from IntPtr to HBITMAP requires a double cast. Like this:

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);
}

Add an assembly reference to System.Drawing. You might then also want to consider passing a Bitmap^ instead of an IntPtr to make it even easier to use.

Sign up to request clarification or add additional context in comments.

Comments

1

You could probably skip the managed C++ wrapper entirely and just call the unmanaged DLL from C# via P/Invoke. Put something like this in your C# class

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

I haven't tested this, so you may need to tweak it as needed, but that's the general idea.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.