C#UnionStructureMarshalling我正在尝试将Video4Linux集成到我的托管应用程序中。事实上,我已经声明了所有必需的结构和相关的ioctl。在这个问题中,我提出了两个ioctl:SetFormat和GetFormat;虽然前者工作正常(正如我实际使用的那样),但后者给了我不好的记忆。GetFormatioctl实际上正在执行,但是一旦应用程序访问ioctl参数(调试器或我的应用程序本身),它总是会崩溃并出现以下堆栈:System.NullReferenceException:...atSystem.String.mempy4(...)in:0atSystem.String.memcpy(...)in:0atDerm.Platform.Video4Linux.ControlGetFormat(...)in...我对p/callioctl做了一些调查,我可以'弄清楚为什么我的应用程序崩溃了。我怀疑这是由于结构内存布局,但我无法解释为什么SetFormat有效而GetFormat无效(因为它们使用相同的参数)。我必须P/Invoke接收/返回结构v4l2_format的ioctl示例程序:structv4l2_format{enumv4l2_buf_typetype;union{structv4l2_pix_formatpix;/*V4L2_BUF_TYPE_VIDEO_CAPTURE*/structv4l2_pix_format_mplanepix_mp;/*V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE*/structv4l2_windowwin;/*V4L2_BUF_TYPE_VIDEO_OVERLAY*/structv4l2_vbi_formatvbi;/*V4L2_BUF_TYPE_VBI_CAPTURE*/structv4l2_sliced_vbi_formatsliced;/*V4L2_BUF_TYPE_SLICED_VBI_CAPTURE*/__u8raw_data[200];/*用户定义*/}fmt;};结构v4l2_pix_format{__u32宽度;__u32高度;__u32像素格式;枚举v4l2_field字段;__u32bytesperline;/*用于填充,如果未使用则为零*/__u32sizeimage;枚举v4l2_colorspace色彩空间;__u32私人;/*私有数据,取决于像素格式*/};我使用下面的表格来描述结构v4l2_format[StructLayout(LayoutKind.Explicit,Pack=4,CharSet=CharSet.Ansi)]publicstructFormat{publicFormat(BufferTypebufferType){Type=bufferType;Pixmap=newPixmapFormat();原始数据=新字节[原始数据长度];}publicFormat(BufferTypebufferType,PixmapFormatpixmapFormat){Type=bufferType;像素图=pixmapFormat;RawData=新字节[RawDataLength];}[FieldOffset(0)]publicBufferType类型;[FieldOffset(4)]publicPixmapFormat像素图;[FieldOffset(4)][MarshalAs(UnmanagedType.ByValArray,SizeConst=RawDataLength)]publicbyte[]RawData;publicconstintRawDataLength=200;}[StructLayout(LayoutKind.Sequential,Pack=4)]publicstructPixmapFormat{publicPixmapFormat(uintwidth,uintheight,PixelFormatCodepixelFormat){Width=width;身高=身高;像素格式=像素格式;Field=Video4Linux.BufferField.Any;每行字节数=0;尺寸图像=0;Colorspace=Video4Linux.PixelColorspace.None;私人=0;}公共UInt32宽度;公共UInt32高度;公共像素格式代码像素格式;公共缓冲区字段;公共UInt32BytesPerLine;公共UInt32SizeImage;公共PixelColorspace色彩空间;公共UInt32私有;}最后,这是调用ioctl的方法:publicstaticvoidControlGetFormat(IntPtrfd,BufferTypepixmapType,outPixmapFormatpixmapFormat){if(fd==IntPtr.Zero)thrownewArgumentException("invalidfiledescriptor","fd");格式format=newFormat(pixmapType);intresult=IoCtrlGetFormat(fd,GetFormat.ControlCode,ref格式);如果(结果<0)ThrowExceptionOnError();pixmapFormat=format.Pixmap;}privatestaticreadonlyIoCtrlRequestGetFormat=newIoCtrlRequest(IoCtrlDirection.Read|IoCtrlDirection.Write,'V',4,typeof(Format));[DllImport("libc",EntryPoint="ioctl",SetLastError=true)]privatestaticexternintIoCtrlGetFormat(IntPtrfd,Int32code,refFormatargument);publicstaticvoidControlSetFormat(IntPtrfd,BufferTypepixmapType,refPixmapFormatpixmapFormat){if(fd==IntPtr.Zero)thrownewArgumentException("无效文件描述符","fd");PixmapFormatpixmapFormatCopy=pixmapForm在;格式format=newFormat(pixmapType,pixmapFormatCopy);intresult=IoCtrlSetFormat(fd,SetFormat.ControlCode,ref格式);如果(结果<0)ThrowExceptionOnError();pixmapFormat=format.Pixmap;}privatestaticreadonlyIoCtrlRequestSetFormat=newIoCtrlRequest(IoCtrlDirection.Read|IoCtrlDirection.Write,'V',5,typeof(Format));[DllImport("libc",EntryPoint="ioctl",SetLastError=true)]privatestaticexternintIoCtrlSetFormat(IntPtrfd,Int32code,refFormatargument);通过将结构大小强制为实际大小(在我的例子中为204)并删除数组字段RawData(如DavidHeffernan所建议的那样)解决了这个问题事实上:[StructLayout(LayoutKind.Explicit,Pack=4,CharSet=CharSet.Ansi,Size=204)]publicstructFormat{publicFormat(BufferTypebufferType){Type=bufferType;Pixmap=newPixmapFormat();}publicFormat(BufferTypebufferType,PixmapFormatpixmapFormat){Type=bufferType;像素图=pixmapFormat;}[FieldOffset(0)]publicBufferType类型;[FieldOffset(4)]publicPixmapFormat像素图;}当然是Marshal.SizeOf(typeof(Format))==204以上就是C#学习教程:C#联盟结构群分享的全部内容。如果对你有用,需要进一步了解C#学习教程,希望大家多多关注。本文收集自网络,不代表立场。如涉及侵权,请点击右边联系管理员删除。如需转载请注明出处:
