Передача растрового изображения из C # в C ++ Неуправляемый код - PullRequest
3 голосов
/ 14 января 2012

Я безуспешно пытаюсь написать код на C # для передачи растрового изображения в неуправляемую DLL-библиотеку c ++ и возврата структуры POINT.

Я провел много исследований в интернете, но не нашел статьи "Gotcha" или фрагмента кода, которые помогли бы мне решить мою проблему.

Лучшее, что я смог до сих пор придумать, - это неуправляемая DLL-библиотека c ++, обернутая управляемой DLL-библиотекой c ++, вызываемой моим C # -приложением. При тестировании я могу передать простые типы, такие как целое число, и без проблем вернуть целое число. Теперь о проблеме, которая у меня есть, растровое изображение.

Я попытался передать HBITMAP (используя функцию GetHBitmap () моего растрового изображения в c #), но я получаю ошибки во время компиляции «не могу преобразовать параметр 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 ++, который используется для поиска изображения в другом изображении, которое работает довольно быстро. К сожалению, даже используя lockbits в c #, это не достаточно быстро. Поэтому я хотел бы использовать код C ++ для поиска изображений.

Я уверен, что столкнусь с дальнейшими трудностями, но, возможно, смогу справиться с этим, если смогу преодолеть этот камень преткновения. Как видите, мои знания C ++ ограничены.

Ответы [ 2 ]

3 голосов
/ 14 января 2012

Вы не можете использовать нативные типы структуры в качестве возвращаемого значения, 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 голос
/ 14 января 2012

Вероятно, вы можете полностью пропустить управляемую оболочку C ++ и просто вызвать неуправляемую DLL из C # через P / Invoke. Поместите что-то подобное в ваш класс C #

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

Я не проверял это, поэтому вам может понадобиться настроить его по мере необходимости, но это общая идея.

...