P/Invoke ioctl system call

前端 未结 1 1221
隐瞒了意图╮
隐瞒了意图╮ 2020-12-18 14:36

I\'m developing an application which needs to interact with Video4Linux abstraction. The application is developed in C#, using the mono framework.

The problem I\'m f

相关标签:
1条回答
  • 2020-12-18 15:06

    Example usage:

    Capability capability;
    
    if (UnsafeNativeMethods.Ioctl(handle, request, ref capability) == -1)
    {
        throw new UnixIOException();
    }
    

    Capability:

    [StructLayout(LayoutKind.Sequential, Size = 104)]
    internal struct Capability
    {
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]
        public string Driver;
    
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
        public string Device;
    
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
        public string BusInfo;
    
        public uint Version;
    
        public CapabilityFlags Capabilities;
    }
    

    UnsafeNativeMethods:

    internal static class UnsafeNativeMethods
    {
        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
        [DllImport("libc", EntryPoint = "close", SetLastError = true)]
        internal static extern int Close(IntPtr handle);
    
        [DllImport("libc", EntryPoint = "ioctl", SetLastError = true)]
        internal static extern int Ioctl(SafeUnixHandle handle, uint request, ref Capability capability);
    
        [DllImport("libc", EntryPoint = "open", SetLastError = true)]
        internal static extern SafeUnixHandle Open(string path, uint flag, int mode);
    
        internal static string Strerror(int error)
        {
            try
            {
                var buffer = new StringBuilder(256);
                var result = Strerror(error, buffer, (ulong)buffer.Capacity);
                return (result != -1) ? buffer.ToString() : null;
            }
            catch (EntryPointNotFoundException)
            {
                return null;
            }
        }
    
        [DllImport("MonoPosixHelper", EntryPoint = "Mono_Posix_Syscall_strerror_r", SetLastError = true)]
        private static extern int Strerror(int error, [Out] StringBuilder buffer, ulong length);
    }
    

    SafeUnixHandle:

    [SecurityPermission(SecurityAction.InheritanceDemand, UnmanagedCode = true)]
    [SecurityPermission(SecurityAction.Demand, UnmanagedCode = true)]
    internal sealed class SafeUnixHandle : SafeHandle
    {
        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
        private SafeUnixHandle()
            : base(new IntPtr(-1), true)
        {
        }
    
        public override bool IsInvalid
        {
            get { return this.handle == new IntPtr(-1); }
        }
    
        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
        protected override bool ReleaseHandle()
        {
            return UnsafeNativeMethods.Close(this.handle) != -1;
        }
    }
    

    UnixIOException:

    [Serializable]
    public class UnixIOException : ExternalException
    {
        private readonly int nativeErrorCode;
    
        [SecurityPermission(SecurityAction.Demand, UnmanagedCode = true)]
        public UnixIOException()
            : this(Marshal.GetLastWin32Error())
        {
        }
    
        [SecurityPermission(SecurityAction.Demand, UnmanagedCode = true)]
        public UnixIOException(int error)
            : this(error, GetErrorMessage(error))
        {
        }
    
        [SecurityPermission(SecurityAction.Demand, UnmanagedCode = true)]
        public UnixIOException(string message)
            : this(Marshal.GetLastWin32Error(), message)
        {
        }
    
        public UnixIOException(int error, string message)
            : base(message)
        {
            this.nativeErrorCode = error;
        }
    
        public UnixIOException(string message, Exception innerException)
            : base(message, innerException)
        {
        }
    
        protected UnixIOException(SerializationInfo info, StreamingContext context)
            : base(info, context)
        {
            this.nativeErrorCode = info.GetInt32("NativeErrorCode");
        }
    
        public int NativeErrorCode
        {
            get { return this.nativeErrorCode; }
        }
    
        public override void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            if (info == null)
            {
                throw new ArgumentNullException("info");
            }
    
            info.AddValue("NativeErrorCode", this.nativeErrorCode);
            base.GetObjectData(info, context);
        }
    
        private static string GetErrorMessage(int error)
        {
            var errorDescription = UnsafeNativeMethods.Strerror(error);
            return errorDescription ?? string.Format("Unknown error (0x{0:x})", error);
        }
    }
    
    0 讨论(0)
提交回复
热议问题