tags:

views:

351

answers:

1

I am trying to retrieve Tiff image data through COM using a StringBuilder but the buffer only has a length of 3 after the COM call. I am converting a VB.NET version to C# which uses a String instead of StringBuilder and is working just fine. If anyone has any suggestions or can point me to some good reading material I would appreciate it.

COM Function signature:

ULONG MTMICRGetImage (char *pcDevName, char *pcImageID, char *pcBuffer, DWORD *pdwLength

);

[DllImport("mtxmlmcr", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
    public static extern Int32 MTMICRGetImage(string DeviceName, string ImageId, StringBuilder ImageBuffer, ref Int32 ImageSize);

COM Call code:

    ImageSize = Convert.ToInt32(mtValue.ToString());
    TempImage = new StringBuilder(ImageSize);
    mtValueSize = 9216;

    RC = MTMICRGetIndexValue(mtDocInfo, "ImageInfo", "ImageURL", 2, mtValue, ref mtValueSize);

    // Allocate memory for image with size of ImageSize
    RC = MTMICRGetImage(ExcellaDeviceName, mtValue.ToString(), TempImage, ref ImageSize);

EDIT: I believe this is due to the binary data and how it is Marshalled, character 4 in the string is a Null character. According to Marshal.PtrToStringAuto() / Marshal.PtrToStringUni(), all characters up to the first null character are copied.

A: 

I figured it out. The issue was caused due to null characters terminating the StringBuilder when being Marshalled. Instead I had to use a IntPtr and read the bytes directly out of memory into a byte array. See below for solution.

[DllImport("mtxmlmcr", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
static extern Int32 MTMICRGetImages(string DeviceName, ref MagTekImage MagTekGImages, ref Int32 TotalImages);


// 
// Allocate memory for image with size of imageSize, because the image
// data has null characters (which marshalling doesn't like), we must
// get the memory location of the char* and read bytes directly from memory
//
IntPtr ptr = Marshal.AllocHGlobal(imageSize + 1);
RC = MTMICRGetImage(ExcellaDeviceName, mtValue.ToString(), ptr, ref imageSize);

// Copy the Image bytes from memory into a byte array for storing
byte[] imageBytes = new byte[imageSize];
Marshal.Copy(ptr, imageBytes, 0, imageSize);
Marshal.FreeHGlobal(ptr);
aurealus
Inspiration from http://bytes.com/topic/c-sharp/answers/251820-stringbuilder-help
aurealus