3

ビットマップをアンマネージ C++ DLL に渡し、POINT 構造体を返すコードを C# で記述しようとしていますが、成功しませんでした。

インターネットで多くの調査を行いましたが、問題の解決に役立つ「Gotcha」の記事やコードが見つかりませんでした。

これまでに思いついた最高のものは、私の C# アプリによって呼び出されたマネージ C++ DLL でラップされたアンマネージ C++ DLL です。テストでは、整数などの単純な型を渡し、問題なく整数を返すことができました。今私が抱えている問題、ビットマップについて。

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# でロックビットを使用しても、十分な速度ではありません。そこで、画像検索に 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にアセンブリ参照を追加します。次に、IntPtrの代わりにBitmap ^を渡すことを検討して、さらに使いやすくすることもできます。

于 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 に答える