Ok guys, this is making me crazy. I'm creating a port for a C lib in C# but I've a problem in using a bitmap (generated with gdi) with a byte array (required from the c lib)
Here are is the code, (pastie) divided in files:
- Lglcd.dll: http://pastie.org/1424596 (compiled)
- G19dotNet.dll: http://pastie.org/1424600 (compiled, this is the interop lib for c#)
- TestProject: http://pastie.org/1424603 (compile, but throws an exception)
The problem is in the last file (the other two are pretty straightforward), line 116
res = LgLcd.NativeMethods.lgLcdUpdateBitmap(openContext.device, ref bmp.hdr, LgLcd.NativeConstants.LGLCD_SYNC_UPDATE(LgLcd.NativeConstants.LGLCD_PRIORITY_NORMAL));
This throws an exception for an invalid memory access to managed memory.
The signature of the function is this one:
/// Return Type: DWORD->unsigned int
///device: int
///bitmap: lgLcdBitmapHeader*
///priority: DWORD->unsigned int
[System.Runtime.InteropServices.DllImportAttribute("LgLcd", EntryPoint = "lgLcdUpdateBitmap")]
public static extern uint lgLcdUpdateBitmap([System.Runtime.InteropServices.In] int device, [System.Runtime.InteropServices.In] ref lgLcdBitmapHeader bitmap, [System.Runtime.InteropServices.In] uint priority);
As you can see the second param is a pointer to lgLcdBitmapHeader, but I suppose (because I've seen an older version of the lib) that this pointer is casted to a lgLcdBitmapQVGAx32 pointer (which is a struct of different size)
I think the problem is there, however I can't manage to solve this, really
here is the signature of the struct:
[System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
public struct lgLcdBitmapHeader
{
/// DWORD->unsigned int
public uint Format;
}
and
[System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
public struct lgLcdBitmap160x43x1
{
/// lgLcdBitmapHeader->Anonymous_5fa96ca7_9cc3_4b33_b5aa_ccff9833813a
public lgLcdBitmapHeader hdr;
/// BYTE[]
//public fixed byte pixels[NativeConstants.LGLCD_BMP_WIDTH * NativeConstants.LGLCD_BMP_HEIGHT * NativeConstants.LGLCD_BMP_BPP];
[System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst = NativeConstants.LGLCD_BMP_WIDTH * NativeConstants.LGLCD_BMP_HEIGHT * NativeConstants.LGLCD_BMP_BPP)]
public byte[] pixels;
public static int SizeConst { get { return NativeConstants.LGLCD_BMP_WIDTH * NativeConstants.LGLCD_BMP_HEIGHT * NativeConstants.LGLCD_BMP_BPP; } }
}
I hope someone can help me, I'm watching all over the web and I've found a .net port of this lib but it's very old, and doesn't have the problem that I have because doesn't use colored bitmaps (with 4 bytes for each color) and doesn't use lgLcdBitmapHeader struct (it uses a simpler one). Also it's source code is very similar to mine.
Any help will be appreciated
Useful Links:
http://lglcdnet.codeplex.com/SourceControl/changeset/changes/5538
Update 1:
I did some progress based on a teory.
DWORD WINAPI lgLcdUpdateBitmap(IN int device,
IN const lgLcdBitmapHeader *bitmap,
IN DWORD priority);
This signature has "a meaning" in c, because the pointer to the first element of a struct is also the pointer to that struct. In fact lgLcdBitmapQVGAx32 has a first element of type lgLcdBitmapHeader. That said, they are using the possibility of C to cast everything to everything to create a "generic method", because lgLcdBitmapHeader can be both lgLcdBitmap160x43x1 (first elem is lgLcdBitmapHeader) or lgLcdBitmapQVGAx32.
This is a problem because in C# I can't emulate this capacity, so I created some "helper" functions which accept lgLcdBitmap160x43x1 and lgLcdBitmapQVGAx32 which are internally used as pointers to lgLcdBitmapHeader.
This done, however, gave me another error:
System.Runtime.InteropServices.MarshalDirectiveException non è stata gestita
Message=Impossibile effettuare il marshalling di 'parameter #2': Limitazione interna: la struttura è troppo complessa o troppo grande.
Source=G19dotNet
StackTrace:
in G19dotNet.LgLcd.NativeMethods.lgLcdUpdateBitmapQVGAx32(Int32 device, lgLcdBitmapQVGAx32& bitmap, UInt32 priority)
in ConsoleTest2.Program.Main(String[] args) in C:\Documents and Settings\Administrator\documenti\visual studio 2010\Projects\G19dotNet\ConsoleTest2\Program.cs:riga 116
in System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
in System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
in Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
in System.Threading.ThreadHelper.ThreadStart_Context(Object state)
in System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx)
in System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
in System.Threading.ThreadHelper.ThreadStart()
InnerException:
English version of System.Runtime.InteropServices.MarshalDirectiveException non è stata gestita Message=Impossibile effettuare il marshalling di 'parameter #2': Limitazione interna: la struttura è troppo complessa o troppo grande.:
System.Runtime.InteropServices.MarshalDirectiveException not handled Message=Impossible do marshalling of 'parameter #2': Internal limitation: the structure is too big or too complex
It has an array of 307200 bytes, what should I do?
Update 2:
I managed to show an image on my screen, means that my teory was correct, I had to use this type of "thing" to make it works: http://bytes.com/topic/c-sharp/answers/272048-internal-limitation-structure-too-complex-too-large However the image shown is "broken", I mean it has the shape of the original image but a bit confused and uncolored, maybe because the way on how I pass the bitmap?