好了,伙计们,这让我发疯了。
我正在为C中的C库创建一个端口,但在使用位图(由GDI生成)和字节数组(C库中必需)时遇到问题
下面是在文件中划分的代码(粘贴):
lglcd.dll:http://pastie.org/1424596
(编译)
g19dotnet.dll:
http://pastie.org/1424600(编译,
这是C的互操作库
测试项目:
http://pastie.org/1424603(编译,
但抛出了一个例外)
问题出在最后一个文件中(另外两个文件非常简单),第116行
res = LgLcd.NativeMethods.lgLcdUpdateBitmap(openContext.device, ref bmp.hdr, LgLcd.NativeConstants.LGLCD_SYNC_UPDATE(LgLcd.NativeConstants.LGLCD_PRIORITY_NORMAL));
这将引发对托管内存的无效内存访问的异常。
函数的签名如下:
/// 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);
正如您所看到的,第二个参数是指向lglcdbitmapHeader的指针,但是我假设(因为我看到了旧版本的lib),这个指针被投射到lglcdbitmapqvgax32指针(它是一个不同大小的结构)
我想问题就在那里,但是我无法解决,真的
以下是结构的签名:
[System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
public struct lgLcdBitmapHeader
{
/// DWORD->unsigned int
public uint Format;
}
和
[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; } }
}
我希望有人能帮我,我在网上到处看,我找到了这个库的一个.net端口,但是它很旧,没有我遇到的问题,因为它没有使用彩色位图(每种颜色有4个字节),也没有使用lglcdbitmapHeader结构(它使用了一个更简单的结构)。它的源代码和我的非常相似。
任何帮助都将不胜感激
有用的链接:
http://lglcdnet.codeplex.com/SourceControl/changeset/changes/5538
更新1:
我做了一些基于理论的进展。
DWORD WINAPI lgLcdUpdateBitmap(IN int device,
IN const lgLcdBitmapHeader *bitmap,
IN DWORD priority);
这个签名在C中有“一个含义”,因为指向结构的第一个元素的指针也是指向该结构的指针。
实际上,lglcdbitmapqvgax32有一个lglcdbitmapheader类型的第一个元素。
也就是说,他们使用c的可能性将所有内容都转换为所有内容来创建“泛型方法”,因为lglcdbitmapHeader可以是lglcdbitmap160x43x1(第一个elem是lglcdbitmapHeader)或lglcdbitmapqvgax32。
这是一个问题,因为在C中我无法模拟此容量,所以我创建了一些“helper”函数,这些函数接受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:
System.Runtime.InteropServices.MarshalDirectiveException Non_stata Gestita的英文版本
信息=不可能有效的编组参数2:Limitazione interna:la struttura_troppo complessa o troppo grande.:
未处理System.Runtime.InteropServices.MarshalDirectiveException
Message=无法对“parameter 2”进行封送处理:内部限制:结构太大或太复杂
它有307200字节的数组,我该怎么办?
更新2:
我设法在我的屏幕上显示了一个图像,这意味着我的理论是正确的,我不得不使用这种类型的“东西”来让它工作:http://bytes.com/topic/c-sharp/answers/272048-internal-limitation-structure-too-complex-too-large
但是显示的图像是“破碎的”,我的意思是它有原始图像的形状但是有点混乱和不着色,可能是因为我如何传递位图的方式?
最佳答案
需要使用非托管分配,正如问题中直接解释的那样。
代码示例:
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);
我还需要更改外部方法签名:
[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);