Ok,大家好,这让我疯了。
我正在为C#创建一个C库的端口,但是在使用位图(由gdi生成)和字节数组(c lib所需)时遇到问题。
下面是代码(pastie),分为几个文件:
我希望有人能够帮助我,我在网上搜索了很多,找到了这个库的 .net 版本,但它非常古老,并且没有我遇到的问题,因为它不使用彩色位图(每种颜色都有 4 个字节),也不使用 lgLcdBitmapHeader 结构体(它使用一个更简单的结构体)。此外,它的源代码与我的非常相似。
任何帮助将不胜感激。
有用的链接:
这个签名在C语言中有着“特殊的含义”,因为结构体的第一个元素的指针也是该结构体的指针。 事实上,lgLcdBitmapQVGAx32的第一个元素的类型是lgLcdBitmapHeader。 也就是说,他们利用C语言将所有东西转换为任何东西的可能性来创建一个“通用方法”,因为lgLcdBitmapHeader既可以是lgLcdBitmap160x43x1(第一个元素是lgLcdBitmapHeader),也可以是lgLcdBitmapQVGAx32。
这是一个问题,因为在C#中我无法模拟这种能力,所以我创建了一些“辅助”函数,它们接受lgLcdBitmap160x43x1和lgLcdBitmapQVGAx32,并在内部将它们用作指向lgLcdBitmapHeader的指针。
然而,这样做却给我带来了另一个错误:
下面是代码(pastie),分为几个文件:
- Lglcd.dll: http://pastie.org/1424596 (已编译)
- G19dotNet.dll: http://pastie.org/1424600 (已编译, 这是C#的Interop库)
- TestProject: http://pastie.org/1424603 (已编译, 但抛出异常)
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的指针,但我猜测(因为我看到了库的旧版本)这个指针被转换为一个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(第一个元素是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:
System.Runtime.InteropServices.MarshalDirectiveException未处理 Message=无法对“参数#2”进行封送:内部限制:结构太复杂或太大。
它有一个307200字节的数组,我该怎么办?
更新2:
我设法在屏幕上显示图像,这意味着我的理论是正确的,我必须使用这种类型的“东西”才能使其工作:http://bytes.com/topic/c-sharp/answers/272048-internal-limitation-structure-too-complex-too-large 但是所显示的图像是“损坏的”,我的意思是它具有原始图像的形状,但有点混乱和无色,也许是因为我传递位图的方式?