Calling C++ Image API from C#
-
Ok, it's pretty weird... I am not sure what is going on here. The correct way to import MY_IMAGE type and the function is as I told you before, there is no need of marshaling for any field. You might try a little change, using Marshal.UnsafeAddrOfPinnedArrayElement instead of AddrOfPinnedObject method of GCHandle class, I mean, you first pin the buffers with GCHandle and then set the address in pbuf fields this way:
img1.pbuf = Marshal.UnsafeAddrOfPinnedArrayElement(buffer1, 0);
img2.pbuf = Marshal.UnsafeAddrOfPinnedArrayElement(buffer2, 0);If it still does not work, you might try allocating the buffers directly in the global heap, with Marshal.AllocHGlobal (remember to free this memory when you don't need it any more), instead of creating them in the managed heap as we did before when instantiated the buffers with new byte[size]. If this works you should then copy the buffers allocated in the global heap to the managed heap with the method Marshal.Copy.
Erik - Thanks for your help. I have it working now. The reason it was failing after the last step was due to other settings that had to be set on the scanner. The vendor makes a single side and double side scanner. The sample in the documetation does not match the process. I dug around in the C++ sample and found other settings that I was able to specify before scanning the card.
-
Erik - Thanks for your help. I have it working now. The reason it was failing after the last step was due to other settings that had to be set on the scanner. The vendor makes a single side and double side scanner. The sample in the documetation does not match the process. I dug around in the C++ sample and found other settings that I was able to specify before scanning the card.
-
Ok, it's pretty weird... I am not sure what is going on here. The correct way to import MY_IMAGE type and the function is as I told you before, there is no need of marshaling for any field. You might try a little change, using Marshal.UnsafeAddrOfPinnedArrayElement instead of AddrOfPinnedObject method of GCHandle class, I mean, you first pin the buffers with GCHandle and then set the address in pbuf fields this way:
img1.pbuf = Marshal.UnsafeAddrOfPinnedArrayElement(buffer1, 0);
img2.pbuf = Marshal.UnsafeAddrOfPinnedArrayElement(buffer2, 0);If it still does not work, you might try allocating the buffers directly in the global heap, with Marshal.AllocHGlobal (remember to free this memory when you don't need it any more), instead of creating them in the managed heap as we did before when instantiated the buffers with new byte[size]. If this works you should then copy the buffers allocated in the global heap to the managed heap with the method Marshal.Copy.
Erik, I wanted to thank you again for the assistance. I was able to confirm that the code require the buffer and pinning/marshaling of the memory and it will not work correctly without the suggestions you provided. I also wanted to let you know what compounded the testing issue with the error was due to incomplete documentation. After getting the process to work, I was able to change certain settings and was able to cause the process to fail. Basically, the image class has to define the height and width to the MAXIMUM allowed image that the scanner can accept. Then the buffer size is set to the max height * max width * single/double scanner mode. Once the scanner returns the image, it adjusts the height and buffer values to be what are read in from the scanner. If the image sizes are specified incorrectly/too small, the API will cause a memory error. For example, the image of the scanned area may be 4" but the scanner's read head is capable of scanning a wider area. So the image width has to be pre-set the maximum width of the read head and not the width of the item that is being scanned. BTW, these maximum values are not specified in the documentation or samples. I actually had to dig thru a C++ sample application and the header files to find these settings. Thanks again.
-
Erik, I wanted to thank you again for the assistance. I was able to confirm that the code require the buffer and pinning/marshaling of the memory and it will not work correctly without the suggestions you provided. I also wanted to let you know what compounded the testing issue with the error was due to incomplete documentation. After getting the process to work, I was able to change certain settings and was able to cause the process to fail. Basically, the image class has to define the height and width to the MAXIMUM allowed image that the scanner can accept. Then the buffer size is set to the max height * max width * single/double scanner mode. Once the scanner returns the image, it adjusts the height and buffer values to be what are read in from the scanner. If the image sizes are specified incorrectly/too small, the API will cause a memory error. For example, the image of the scanned area may be 4" but the scanner's read head is capable of scanning a wider area. So the image width has to be pre-set the maximum width of the read head and not the width of the item that is being scanned. BTW, these maximum values are not specified in the documentation or samples. I actually had to dig thru a C++ sample application and the header files to find these settings. Thanks again.