Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# .net wrapper for c dll, specifically lglcd (g19 sdk)

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:

  1. Lglcd.dll: http://pastie.org/1424596 (compiled)
  2. G19dotNet.dll: http://pastie.org/1424600 (compiled, this is the interop lib for c#)
  3. 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?

like image 929
Francesco Belladonna Avatar asked Jan 03 '11 01:01

Francesco Belladonna


People also ask

What C is used for?

C programming language is a machine-independent programming language that is mainly used to create many types of applications and operating systems such as Windows, and other complicated programs such as the Oracle database, Git, Python interpreter, and games and is considered a programming foundation in the process of ...

What is the full name of C?

In the real sense it has no meaning or full form. It was developed by Dennis Ritchie and Ken Thompson at AT&T bell Lab. First, they used to call it as B language then later they made some improvement into it and renamed it as C and its superscript as C++ which was invented by Dr. Stroustroupe.

Is C language easy?

C is a general-purpose language that most programmers learn before moving on to more complex languages. From Unix and Windows to Tic Tac Toe and Photoshop, several of the most commonly used applications today have been built on C. It is easy to learn because: A simple syntax with only 32 keywords.

Is C programming hard?

C is more difficult to learn than JavaScript, but it's a valuable skill to have because most programming languages are actually implemented in C. This is because C is a “machine-level” language. So learning it will teach you how a computer works and will actually make learning new languages in the future easier.


1 Answers

Usage of unmanaged allocation is needed 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);

Also I needed to change the extern method signature:

    [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);
like image 147
Francesco Belladonna Avatar answered Sep 28 '22 08:09

Francesco Belladonna