我正在尝试将Video4Linux集成到我的托管应用程序中。实际上我已经声明了所有必需的结构和相对的 ioctl 。在这个问题中,我提出了两个ioctl
:SetFormat
和GetFormat
;虽然前者运作良好(就像我实际使用的那样),后者却让我记忆力不好。
GetFormat
ioctl实际上正在执行,但是一旦应用程序访问ioctl参数(调试器或我的应用程序本身),它总是会崩溃并跟随以下堆栈:
System.NullReferenceException: ...
at System.String.mempy4(...) in <filename unknown>:0
at System.String.memcpy(...) in <filename unknown>:0
at Derm.Platform.Video4Linux.ControlGetFormat(...) in <...>
...
我对p/invoking ioctl进行了一些调查,再一次,我无法理解为什么我的应用程序崩溃了。我怀疑它是由于结构内存布局,但我无法解释为什么SetFormat
正在工作而GetFormat
没有(因为它们使用相同的参数)。
我必须P / Invoke接收/返回结构ioctl
的{{1}}例程:
v4l2_format
我使用以下表格
来描述结构struct v4l2_format {
enum v4l2_buf_type type;
union {
struct v4l2_pix_format pix; /* V4L2_BUF_TYPE_VIDEO_CAPTURE */
struct v4l2_pix_format_mplane pix_mp; /* V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE */
struct v4l2_window win; /* V4L2_BUF_TYPE_VIDEO_OVERLAY */
struct v4l2_vbi_format vbi; /* V4L2_BUF_TYPE_VBI_CAPTURE */
struct v4l2_sliced_vbi_format sliced; /* V4L2_BUF_TYPE_SLICED_VBI_CAPTURE */
__u8 raw_data[200]; /* user-defined */
} fmt;
};
struct v4l2_pix_format {
__u32 width;
__u32 height;
__u32 pixelformat;
enum v4l2_field field;
__u32 bytesperline; /* for padding, zero if unused */
__u32 sizeimage;
enum v4l2_colorspace colorspace;
__u32 priv; /* private data, depends on pixelformat */
};
v4l2_format
最后,这是调用ioctl的方法:
[StructLayout(LayoutKind.Explicit, Pack = 4, CharSet = CharSet.Ansi)]
public struct Format
{
public Format(BufferType bufferType)
{
Type = bufferType;
Pixmap = new PixmapFormat();
RawData = new byte[RawDataLength];
}
public Format(BufferType bufferType, PixmapFormat pixmapFormat)
{
Type = bufferType;
Pixmap = pixmapFormat;
RawData = new byte[RawDataLength];
}
[FieldOffset(0)]
public BufferType Type;
[FieldOffset(4)]
public PixmapFormat Pixmap;
[FieldOffset(4)]
[MarshalAs(UnmanagedType.ByValArray, SizeConst=RawDataLength)]
public byte[] RawData;
public const int RawDataLength = 200;
}
[StructLayout(LayoutKind.Sequential, Pack = 4)]
public struct PixmapFormat
{
public PixmapFormat(uint width, uint height, PixelFormatCode pixelFormat)
{
Width = width;
Height = height;
PixelFormat = pixelFormat;
Field = Video4Linux.BufferField.Any;
BytesPerLine = 0;
SizeImage = 0;
Colorspace = Video4Linux.PixelColorspace.None;
Private = 0;
}
public UInt32 Width;
public UInt32 Height;
public PixelFormatCode PixelFormat;
public BufferField Field;
public UInt32 BytesPerLine;
public UInt32 SizeImage;
public PixelColorspace Colorspace;
public UInt32 Private;
}
答案 0 :(得分:4)
通过将结构大小强制为实际大小( 204 ,在我的情况下)来解决问题,并删除数组字段RawData
(由{{3}建议) })。
事实上:
[StructLayout(LayoutKind.Explicit, Pack = 4, CharSet = CharSet.Ansi, Size = 204)]
public struct Format
{
public Format(BufferType bufferType)
{
Type = bufferType;
Pixmap = new PixmapFormat();
}
public Format(BufferType bufferType, PixmapFormat pixmapFormat)
{
Type = bufferType;
Pixmap = pixmapFormat;
}
[FieldOffset(0)]
public BufferType Type;
[FieldOffset(4)]
public PixmapFormat Pixmap;
}
当然,Marshal.SizeOf(typeof(Format)) == 204
。