2

I'm currently trying to integrate a C++ DLL into our C# application, but I'm not able to identify the correct way to call one of their methods.

C++ methods definition:

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++ example code:

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

My C# conversion:

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

If I specify a default value for PicBuffer, using [MarshalAs(UnmanagedType.ByValArray, SizeConst = 99999)], I don't receive a value in lPicSize, and if I don't specify a default value I get a value in lPicSize but it isn't the correct value for PicBuffer.

What am I missing here?

1
  • It's been a while since I did C++ but IMHO the C++ code declares a function pointer, not a method. Commented May 13, 2013 at 12:08

1 Answer 1

3

The native DLL is allocating the memory for the buffer, and returning the unmanaged pointer in the PicBuffer field of the struct. And so your struct declaration is wrong. You need the byte array to be declared as a pointer.

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

The you must call Marshal.Copy to copy the buffer's content to a byte array. For example:

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

Make sure you call FreeImageDataBuffer when you have copied all the buffers. Otherwise you will leak the memory that the native DLL allocated.


Note that in the C++ code, ImageDataAndInfo is the struct and PImageDataAndInfo is a pointer to the struct. So your C# struct should be named ImageDataAndInfo.

Also, you do not need to use new to make new instances of a struct. Just declare them like this:

ImageDataAndInfo PicF1;
ImageDataAndInfo PicF2;
// etc.
Sign up to request clarification or add additional context in comments.

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.