1

C# に基づくメイン プログラムでいくつかのグラフィカル フィルターをプログラミングしています。
ただし、C# は getpixel / putpixel が高速ではありません。
安全なコードとメモリのクリーンアップの利点を理解しているため、C#で安全でないコードを使用すると、安全でないコードを使用すると
、少し危険な気分になります。

だから今、私は疑問に思っています....
この安全でないコードをC++に基づく別のdllに書いた方が良いのでしょうか?.
しかし、私は混合言語プログラムを作ったことがないので、疑問に思っています。

  • C# から C++ の関数にビットマップを渡すにはどうすればよいですか? dll への参照を設定することはできますが、それだけでは十分ではないと思います
  • 戻り値とビットマップを c# メイン プログラムに戻す方法

また、別のコンパイラを使用して c++11 .dll を記述した場合、それは問題になりますか? メインプログラムはVisual Studio 2010 expresで書かれています

4

4 に答える 4

4

実際、CUDAを使用して、あなたが言及したのとまったく同じこと(グラフィカルフィルター)を行っています。マネージド コード (WinForms) から C 関数を呼び出せるようにするために、InteropServices を利用しています。

ソリューションに 2 つのプロジェクト (C++ ライブラリといくつかの C# プロジェクト) があるとします。

C++ ライブラリで関数を宣言するには、次のパラメーターを使用します。

extern "C" int __declspec(dllexport) __stdcall cudaCopyInputData
    (int n, int w, int h, byte* data)
{
    inputBuffer = data;
    bufferLength = n;
    inputWidth = w;
    inputHeight = h;
    useFloatBuffer = 0;
    binaryBufferValid = 0;

    int bufferSize = bufferLength * sizeof(byte);
    int floatBufferSize = bufferLength * sizeof(float);
    int binaryBufferSize = w * h * sizeof(int);

    cudaMalloc((void**)&cudaInputBuffer, bufferSize);
    cudaMemcpy(cudaInputBuffer, inputBuffer, bufferSize, cudaMemcpyHostToDevice);

    cudaMalloc((void**)&cudaFloatBuffer, floatBufferSize);
    cudaMalloc((void**)&cudaBinaryBuffer, binaryBufferSize);

    return 0;
}

C# プロジェクトから使用できるようにするために、InteropServices を使用してこの関数を静的メソッドとしてインポートします。

[DllImport("CUDA Dll.dll", CharSet = CharSet.Ansi, SetLastError = true, CallingConvention = CallingConvention.StdCall)]
        public static extern int cudaCopyInputData(int n, int w, int h, IntPtr data);

その後、マネージ コードから標準的な方法として使用できます。

インポートされたメソッドにビットマップ データを渡すには、次のようなものを使用できます。

BitmapData bmpData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadWrite, PixelFormat.Format32bppRgb);

次に、bmpData.Scan0 をビットマップ データへのポインターとして渡し、幅、高さ、ストライド、または C 関数でデータ形式を把握したいその他のパラメーターを渡します。上記の例では、各ピクセルに 4 バイト (3 バイト + 1 ダミー バイト) があるため、快適に処理できます。

bmp オブジェクトから処理されたデータを再利用するには、処理後に呼び出すだけです。

bmp.UnlockBits(bmpData);
于 2012-10-23T17:06:47.453 に答える
1

C++ を使用している場合は、安全でないコードで C# を使用することもできます。どちらも安全ではなく、C# ではメモリのクリーンアップを気にする必要はありません。あなたが気にしなければならない唯一のことは、無効なポインタにアクセスすることAccessViolationExceptionです.

public unsafe void SwapChannels(Byte[] imageSrc)
{
    fixed (Byte* pImageSrc = imageSrc)
    {
        // Swap channels here
    }
}

画像ライブラリでも安全でないコードを使用しています。クロスプラットフォームにしない場合は、C++/CLI を使用することもできます。

于 2012-10-23T15:25:22.013 に答える
1

C++ と C# の間で相互運用を行うには、C++/CLI、COM、および P/Invoke といういくつかの方法があります。

C++/CLI と COM には、どちらかが優れている領域がありますが、いくつかの簡単なソリューションを除いて、P/Invoke を使用する必要はないと思います。

あなたの場合、特にC++ DLLが別のコンパイラで構築されていると述べているので、COMが最善の策だと思います。

ただし、C++ の使用は、C# でアンセーフ コードを使用するのとほとんど同じであることに注意してください。たとえば、いたるところにポインタがあります。

于 2012-10-23T15:26:33.600 に答える
0

SWIGを使用すると、C++ コードを簡単にラップして、C# でクラス/関数を公開できます。これを使用して、c# で画像処理ルーチンの一部を公開しましたが、簡単です。c# クラスとして動作するクラスになり、SWIG によって生成されたラッパーが型変換 (ほとんど) と P/Invoke を処理します。

この記事を書いている時点で、swig.org のサイトがダウンしています。理由を知っている人がいたら、コメントしてください。

コンパイラの取り違えに関しては、Mingw でコンパイルされた DLL の使用経験が豊富です。

編集:プロジェクトの sourceforge ページには引き続きアクセスできます

于 2012-10-23T15:25:37.327 に答える