2

現在、C++ DLL を C# アプリケーションに統合しようとしていますが、メソッドの 1 つを呼び出す正しい方法を特定できません。

C++ メソッドの定義:

typedef struct ImageDataAndInfo
{ 
    unsigned char* PicBuffer;     //image buffer 
    long lPicSize;    //image data length 
    int iPicType;     // iPicType, 0: bmp, 1: tiff, 2: jpeg 
} ImageDataAndInfo,*PImageDataAndInfo; 

typedef  ImageAndScanError    (__stdcall * ReadPictureData)(PImageDataAndInfo PicF1,
    PImageDataAndInfo PicR1, 
    PImageDataAndInfo PicF2,
    PImageDataAndInfo PicR2,  
    PImageDataAndInfo PicF3,
    PImageDataAndInfo PicR3,  
    BOOL bSourceBMPSave);

typedef  void    (__stdcall * FreeImageDataBuffer)(PImageDataAndInfo pImageDataAndInfo);

C++ のサンプル コード:

ImageDataAndInfo F1,F2,F3,R1,R2,R3;
F1.lPicSize=0;
F2.lPicSize=0;
F3.lPicSize=0;
R1.lPicSize=0;
R2.lPicSize=0;
R3.lPicSize=0;

int bResult;
bResult=ReadPictureData(&F1,&R1,&F2,&R2,&F3,&R3,TRUE);

f_FreeImageDataBuffer(&F1);
...
f_FreeImageDataBuffer(&R3);

私のC#変換:

[StructLayout(LayoutKind.Sequential)]
public struct PImageDataAndInfo
{
    [MarshalAs(UnmanagedType.ByValArray)]
    public byte[] PicBuffer;        //image buffer 

    public int lPicSize;            //image data length 
    public int iPicType;            // iPicType, 0: bmp, 1: tiff, 2: jpeg 
}

[DllImport("ScanDll.dll", CallingConvention = CallingConvention.Winapi)]
public static extern ImageAndScanError ReadPictureData(
    out PImageDataAndInfo PicF1,
    out PImageDataAndInfo PicR1,
    out PImageDataAndInfo PicF2,
    out PImageDataAndInfo PicR2,
    out PImageDataAndInfo PicF3,
    out PImageDataAndInfo PicR3,
    bool bSourceBMPSave);

PImageDataAndInfo PicF1 = new PImageDataAndInfo();
...
PImageDataAndInfo PicR3 = new PImageDataAndInfo();

ReadPictureData(
    out PicF1,
    out PicR1,
    out PicF2,
    out PicR2,
    out PicF3,
    out PicR3,
    false);

PicBufferを使用して のデフォルト値を指定すると、 で値を[MarshalAs(UnmanagedType.ByValArray, SizeConst = 99999)]受け取りませlPicSizeん。デフォルト値を指定しないと、 で値を取得しますlPicSizeが、 の正しい値ではありませんPicBuffer

ここで何が欠けていますか?

4

1 に答える 1

3

ネイティブ DLL はバッファーにメモリを割り当て、PicBuffer構造体のフィールドにアンマネージ ポインターを返します。したがって、構造体宣言が間違っています。バイト配列をポインターとして宣言する必要があります。

[StructLayout(LayoutKind.Sequential)]
public struct ImageDataAndInfo
{
    public IntPtr PicBuffer;       
    public int lPicSize;           
    public int iPicType;           
}

Marshal.Copyバッファの内容をバイト配列にコピーするには、 を呼び出す必要があります。例えば:

// call ReadPictureData
byte[] buffer = new byte[PicF1.lPicSize];
Marshal.Copy(PicF1.PicBuffer, buffer, 0, PicF1.lPicSize);

FreeImageDataBufferすべてのバッファをコピーしたら、必ず呼び出してください。そうしないと、ネイティブ DLL が割り当てたメモリがリークします。


C++ コードでImageDataAndInfoは、 は構造体であり、構造体PImageDataAndInfoへのポインターであることに注意してください。したがって、C# 構造体の名前はImageDataAndInfo.

newまた、構造体の新しいインスタンスを作成するために を使用する必要はありません。次のように宣言するだけです。

ImageDataAndInfo PicF1;
ImageDataAndInfo PicF2;
// etc.
于 2013-05-13T12:07:47.297 に答える