Fir*_*DoL 6 c c# dll interop wrapper
好的,这让我疯了.我正在为C#中的C lib创建一个端口,但我在使用带有字节数组的位图(使用gdi生成)时遇到了问题(需要来自c lib)
这里是代码,(pastie)分为文件:
问题出在最后一个文件中(其他两个非常简单),第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)
正如问题中直接解释的那样,需要使用非托管分配。
代码示例:
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)