C # .net shell for c dll, in particular lglcd (g19 sdk)

Ok guys, this makes me crazy. I am creating a port for C lib in C #, but I have a problem using a bitmap (generated using gdi) with a byte array (required from c lib)

Here is the code, (graze), divided into files:

The problem is in the last file (the other two are quite simple), 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 invalid access to memory in managed memory.

The signature of the function is as follows:

 /// 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 parameter is a pointer to lgLcdBitmapHeader, but I suppose (because I saw an older version of lib) that this pointer is passed to the pointer lgLcdBitmapQVGAx32 (which is a structure of different sizes)

I think there is a problem, however I can not solve this problem, really

here is the signature of the structure:

  [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 look all over the network and I found the .net port of this library, but it is very old and I have no problem because I do not use (with 4 bytes for each color ) and does not use lgLcdBitmapHeader struct (it uses a simpler one). Also, the source code is very similar to mine.

Any help would be appreciated

Useful links:

http://lglcdnet.codeplex.com/SourceControl/changeset/changes/5538

Update 1:

I have made some progress based on theory.

 DWORD WINAPI lgLcdUpdateBitmap(IN int device, IN const lgLcdBitmapHeader *bitmap, IN DWORD priority); 

This signature has a "value" in c because the pointer to the first element of the structure is also a pointer to this structure. Actually, lgLcdBitmapQVGAx32 has the first element of type lgLcdBitmapHeader. However, they use C's ability to drop everything to create a “generic method”, since lgLcdBitmapHeader can be either lgLcdBitmap160x43x1 (the first element is lgLcdBitmapHeader) or lgLcdBitmapQVGAx32.

This is a problem because in C # I cannot emulate this capacity, so I created some "helper" functions that accept lgLcdBitmap160x43x1 and lgLcdBitmapQVGAx32, which are internally used as pointers to lgLcdBitmapHeader.

This made, however, another mistake:

 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': Internship restriction: la struttura è troppo complessa o troppo grande .:

System.Runtime.InteropServices.MarshalDirectiveException is not handled Message = Impossible make marshalling 'parameter # 2': Internal constraint: structure is too big or too complicated

It has an array of 307200 bytes, what should I do?

Update 2:

I managed to show the image on my screen, this means that my theory is correct, I had to use this type of “thing” to make it work: http://bytes.com/topic/c-sharp/answers/272048-internal-limitation -structure-too-complex-too-large However, the image shown is “broken”, I mean that it has the shape of the original image, but a little confused and unpainted, perhaps because the way to transmit the bitmap?

Update 3 and solution:

I solved the problem myself, the code is really ugly, and I will post it here in the paste, I hope someone finds this useful. The most important part of the code is:

 /// <summary> /// LONG GetBitmapBits( /// __in HBITMAP hbmp, /// __in LONG cbBuffer, /// __out LPVOID lpvBits /// ); /// </summary> /// <param name="hbmp"></param> /// <param name="cbBuffer"></param> /// <param name="lpvBits"></param> /// <returns></returns> [DllImport("Gdi32", EntryPoint = "GetBitmapBits")] public extern static long GetBitmapBits([In] IntPtr hbmp,[In] int cbBuffer,[Out] byte[] lpvBits); [DllImport("Gdi32", EntryPoint = "GdiFlush")] public extern static void GdiFlush(); public static void FillPixelArray3(Bitmap bmp, ref byte[] array) { IntPtr hbmp = bmp.GetHbitmap(); GdiFlush(); //Marshal SizeOf is to "ensure" that other people will notice that array.Length //must be multiplied GetBitmapBits(hbmp, array.Length * Marshal.SizeOf(typeof(byte)), array); } 

and this:

  IntPtr unhandledPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(LgLcd.lgLcdBitmapQVGAx32))); Marshal.StructureToPtr(bmp, unhandledPtr, true); res = LgLcd.NativeMethods.lgLcdUpdateBitmap(openContext.device, unhandledPtr, LgLcd.NativeConstants.LGLCD_SYNC_UPDATE(LgLcd.NativeConstants.LGLCD_PRIORITY_NORMAL)); Marshal.FreeHGlobal(unhandledPtr); 
+6
c c # dll interop wrapper
source share
2 answers

The use of unmanaged distribution is necessary, as explained directly in the question.

Code example:

 IntPtr unhandledPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(LgLcd.lgLcdBitmapQVGAx32))); Marshal.StructureToPtr(bmp, unhandledPtr, true); res = LgLcd.NativeMethods.lgLcdUpdateBitmap(openContext.device, unhandledPtr, LgLcd.NativeConstants.LGLCD_SYNC_UPDATE(LgLcd.NativeConstants.LGLCD_PRIORITY_NORMAL)); Marshal.FreeHGlobal(unhandledPtr); 

I also needed to change the signature of the extern method:

  [DllImportAttribute("LgLcd", EntryPoint = "lgLcdUpdateBitmap")] public static extern uint lgLcdUpdateBitmap([In] int device, [In] IntPtr bitmap, [In] uint priority); //OLD ONE: public static extern uint lgLcdUpdateBitmap([In] int device, [In] ref lgLcdBitmapHeader bitmap, [In] uint priority); 
+1
source share

Since you have the source code for c dll, you should consider creating a shell using the Visual C ++ CLR project. Common Language Runtime allows you to write managed and unmanaged code together. Then you do not need to pass variables, but use them directly.

And when you want to use it from C #, just reference the C ++ Clr library from your C # application. I have used this path before and it works great.

0
source share

All Articles