c dll的C#.net包装器,特别是lglcd(g19 sdk)

Fir*_*DoL 6 c c# dll interop wrapper

好的,这让我疯了.我正在为C#中的C lib创建一个端口,但我在使用带有字节数组的位图(使用gdi生成)时遇到了问题(需要来自c lib)

这里是代码,(pastie)分为文件:

  1. Lglcd.dll:http://pastie.org/1424596 (已编译)
  2. G19dotNet.dll:http://pastie.org/1424600 (已编译,这是c#的互操作lib)
  3. TestProject:http: //pastie.org/1424603(编译,但抛出异常)

问题出在最后一个文件中(其他两个非常简单),第116行

res = LgLcd.NativeMethods.lgLcdUpdateBitmap(openContext.device, ref bmp.hdr, LgLcd.NativeConstants.LGLCD_SYNC_UPDATE(LgLcd.NativeConstants.LGLCD_PRIORITY_NORMAL));
Run Code Online (Sandbox Code Playgroud)

这会引发对托管内存的无效内存访问的异常.

功能的签名是这样的:

/// 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);
Run Code Online (Sandbox Code Playgroud)

正如你所看到的那样,第二个param是一个指向lgLcdBitmapHeader的指针,但我想(因为我看过lib的旧版本),这个指针被转换为lgLcdBitmapQVGAx32指针(这是一个不同大小的结构)

我认为存在问题,但是我无法解决这个问题

这是结构的签名:

    [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
    public struct lgLcdBitmapHeader
    {

        /// DWORD->unsigned int
        public uint Format;
    }
Run Code Online (Sandbox Code Playgroud)

    [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; } }
    }
Run Code Online (Sandbox Code Playgroud)

我希望有人可以帮助我,我正在网上看,我已经找到了这个lib的.net端口,但它已经很老了,并且没有我的问题因为没有使用彩色位图(每种颜色有4个字节)并且不使用lgLcdBitmapHeader结构(它使用更简单的结构).它的源代码与我的非常相似.

任何帮助将不胜感激

有用的链接:

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

更新1:

我基于teory做了一些进步.

DWORD WINAPI lgLcdUpdateBitmap(IN int device,
                           IN const lgLcdBitmapHeader *bitmap,
                           IN DWORD priority);
Run Code Online (Sandbox Code Playgroud)

此签名在c中具有"含义",因为指向结构的第一个元素的指针也是指向该结构的指针.实际上,lgLcdBitmapQVGAx32具有类型为lgLcdBitmapHeader的第一个元素.也就是说,他们正在利用C的可能性将所有东​​西都投射到一切来创建"通用方法",因为lgLcdBitmapHeader可以是lgLcdBitmap160x43x1(第一个elem是lgLcdBitmapHeader)或lgLcdBitmapQVGAx32.

这是一个问题,因为在C#中我无法模拟这个容量,因此我创建了一些"辅助"函数,它们接受lgLcdBitmap160x43x1和lgLcdBitmapQVGAx32,它们在内部用作指向lgLcdBitmapHeader的指针.

但是,这样做又给了我一个错误:

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: 
Run Code Online (Sandbox Code Playgroud)

英文版System.Runtime.InteropServices.MarshalDirectiveExceptionnonèstatagestita Message = Impossibile effettuare il marshalling di'参数#2':Limitazione interna:lastrutturaètropropocomplessa o troppo grande.:

未处理System.Runtime.InteropServices.MarshalDirectiveException消息=不可能对"参数#2"进行编组:内部限制:结构太大或太复杂

它有一个307200字节的数组,我该怎么办?

更新2:

我设法在我的屏幕上显示一个图像,意味着我的teory是正确的,我不得不使用这种类型的"东西"使其工作:http://bytes.com/topic/c-sharp/answers/272048-内部限制 - 结构 - 太复杂 - 太大 但是显示的图像是"破碎的",我的意思是它具有原始图像的形状但有点困惑和无色,可能是因为我如何通过位图的方式?

更新3和解决方案:

我自己解决了这个问题,代码非常难看,我会把它贴在里面,希望有人会发现它很有用.代码中最重要的部分是这一部分:

res = LgLcd.NativeMethods.lgLcdUpdateBitmap(openContext.device, ref bmp.hdr, LgLcd.NativeConstants.LGLCD_SYNC_UPDATE(LgLcd.NativeConstants.LGLCD_PRIORITY_NORMAL));
Run Code Online (Sandbox Code Playgroud)

还有这个:

/// 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);
Run Code Online (Sandbox Code Playgroud)

Fir*_*DoL 1

正如问题中直接解释的那样,需要使用非托管分配。

代码示例:

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);
Run Code Online (Sandbox Code Playgroud)

我还需要更改外部方法签名:

    [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);
Run Code Online (Sandbox Code Playgroud)