Unsolved Complex C Structure Marshall Problem
Hi.
If you think you have seen all about Pinvoke, Marshalling, Callbacks, Structures, References... think again.
I have been working on this issue for the last 2 weeks and I have managed to reach partial sucess.
I'm allmost there but I NEED YOUR HELP. Please read on.
Here are the two C legacy structures that I need to use:
---
struct RDSImage
{
long docnumber;
short xorigin;
short yorigin;
short flags;
unsigned char camera;
unsigned char type;
unsigned char blackframe;
unsigned char jquality;
short xresolution;
short yresolution;
char *filefmt;
char *directory;
char *filename;
long onldispwin;
long procarg[3];
unsigned char *pCodeLine;
struct RDSScan *doc;
unsigned char *startaddr;
int length;
short width;
short height;
short color;
}
struct RDSScan
{
unsigned long LastDocScanned;
unsigned short ScanLength;
unsigned short Height[2];
unsigned short ReadMode;
unsigned char Operation;
unsigned char Pocket;
unsigned char LightSourceBack;
unsigned char ResolutionX[2];
unsigned char ResolutionY[2];
unsigned char Brightness[2];
unsigned char Contrast[2];
unsigned short StampPosition;
unsigned char OffsetInkjet;
unsigned char DoubleThreshold;
unsigned char Reserved;
unsigned char InkjetString[80];
unsigned char CodeLine [80];
struct RDSImage *rdsi[6];
}
---
Here is my C# conversion to struct (please verify this):
---
[StructLayout(LayoutKind.Sequential)]
public struct RDS3000Image
{
public Int32 docnumber; // C long
public Int16 xorigin; // C short
public Int16 yorigin; // C short
public Int16 flags; // C short
public Byte camera; // C unsigned char
public Byte type; // C unsigned char
public Byte blackframe; // C unsigned char
public Byte jquality; // C unsigned char
public Int16 xresolution; // C short
public Int16 yresolution; // C short
public IntPtr filefmt; // C char *
public IntPtr directory; // C char *
public IntPtr filename; // C char *
public Int32 onldispwin; // C long
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
public Int32[] procarg; // C long
public IntPtr pCodeline; // C unsigned char *
public IntPtr doc; // Cross pointer to RDSScan
public IntPtr startaddr; // C unsigned char *
public Int32 length; // C long
public Int16 width; // C short
public Int16 height; // C short
public Int16 color; // C short
}
[StructLayout(LayoutKind.Sequential)]
public class RDS3000Scan
{
public UInt32 LastDocScanned; // C unsigned long
public UInt16 ScanLength; // C unsigned short
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
public UInt16[] Height; // C unsigned short
public UInt16 ReadMode; // C unsigned short
public Byte Operation; // C unsigned char
public Byte Pocket; // C unsigned char
public Byte LightSourceBack; // C unsigned char
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
public Byte[] ResolutionX; // C unsigned char
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
public Byte[] ResolutionY; // C unsigned char
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
public Byte[] Brightness; // C unsigned char
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
public Byte[] Contrast; // C unsigned char
public UInt16 StampPosition; // C unsigned short
public Byte OffsetInkjet; // C unsigned char
public Byte DoubleThreshold; // C unsigned char
public Byte reserved; // C unsigned char
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 80)]
public Byte[] InkjetString; // C unsigned char
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 80)]
public Byte[] Codeline; // C unsigned char
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)]
public IntPtr[] rdsi; // Array of pointers to RDSImages.
}
---
I'm calling a C legacy DLL and installing a callback:
---
// DLL full path.
private const String DLL = "c:\\legacy.dll";
// This is the signature of the callback (this will be on my
// managed code):
//
public delegate int ImageStoredCallback(ref SB1600Image rdsimage);
// This is the unmaged function I invoke on the DLL. It allows
// installing a callback:
//
[DllImport(DLL)]
private static extern int rdOnImageStored(int index, ImageStoredCallback address);
// ---
// Note: The above method has the following C signature:
//
// int rdOnImageStored(int index,
// int (*userfunc)(struct RDSImage *));
//
// Notice that, on this signature, the second parameter matches my
// callback signature, define above has:
//
// int ImageStoredCallback(ref SB1600Image rdsimage);
// ---
And here I'm installing the callback (twice, for int 1 and int 4):
private static ImageStoredCallback imageStoredCallbackAddress;
imageStoredCallbackAddress = new ImageStoredCallback(SB1600Callback.ImageStoredCall backImplementation);
rtnval = rdOnImageStored(1, imageStoredCallbackAddress);
rtnval = rdOnImageStored(4, imageStoredCallbackAddress);
So this is it...
What is the problem, you may ask.
Well, Visual Studio 2005 says the code is ok. The callback is installed and runs with no problem. For example, after running the code here is what I get on my screen:
[DEBUG] ->Image Stored callback implementation.
[DEBUG] **** RDSImage Struct ****
[DEBUG] rdsimage.docnumber: 1
[DEBUG] rdsimage.xorigin: 0
[DEBUG] rdsimage.yorigin: 0
[DEBUG] rdsimage.flags: 256
[DEBUG] rdsimage.camera: 2
[DEBUG] rdsimage.type: 5
[DEBUG] rdsimage.blackframe: 0
[DEBUG] rdsimage.jquality: 60
[DEBUG] rdsimage.filefmt: -713161537
[DEBUG] rdsimage.directory: -1430911809
[DEBUG] rdsimage.filename: 1215
[DEBUG] rdsimage.filefmt: ""
[DEBUG] rdsimage.directory: ""
[DEBUG] rdsimage.filename: ""
[DEBUG] rdsimage.onldispwin: 0
[DEBUG] rdsimage.procarg[0]: 0
[DEBUG] rdsimage.procarg[1]: 0
[DEBUG] rdsimage.procarg[2]: 236978176
[DEBUG] rdsimage.pCodeline: 229901568
[DEBUG] rdsimage.doc: 2098432
[DEBUG] rdsimage.startaddr: 967247235
[DEBUG] rdsimage.length: 39321600
[DEBUG] rdsimage.width: 376
[DEBUG] rdsimage.height: 2
[DEBUG] rdsimage.color: 2
[DEBUG] **** RDSImage Struct ****
[DEBUG] <-Image Stored callback implementation.
Things look good but it seems that I'm having problems with the pointers. This does not look normal:
[DEBUG] rdsimage.filefmt: -713161537
[DEBUG] rdsimage.directory: -1430911809
[DEBUG] rdsimage.filename: 1215
[DEBUG] rdsimage.filefmt: ""
[DEBUG] rdsimage.directory: ""
[DEBUG] rdsimage.filename: ""
Here is what I'm using to print this values:
Log.Debug("rdsimage.filefmt: " + rdsimage.filefmt.ToString());
Log.Debug("rdsimage.directory: " + rdsimage.directory.ToString());
Log.Debug("rdsimage.filename: " + rdsimage.filename.ToString());
Log.Debug("rdsimage.filefmt: \"" + Marshal.PtrToStringAuto(rdsimage.filefmt) + "\"");
Log.Debug("rdsimage.directory: \"" + Marshal.PtrToStringAuto(rdsimage.directory) + "\"");
Log.Debug("rdsimage.filename: \"" + Marshal.PtrToStringAuto(rdsimage.filename) + "\"");
So, if you have any sugestion, any comment... anything... I would apreciate it.
I need this solved for a project and the deadline is just around the corner. Help!
John
|