【问题标题】:Dealing with file handles using Mono and P/Invoke使用 Mono 和 P/Invoke 处理文件句柄
【发布时间】:2015-12-29 21:45:06
【问题描述】:

我有一些最初用 Python 编写的代码,我正在尝试将其转换为 C#。它将在 Linux 上运行。

然而,Python 代码会打开一个文件,然后将一些 Linux 特定的ioctl 命令发送到打开的文件。

class i2c(object):
   def __init__(self, device, bus):
      self.fr = io.open("/dev/i2c-"+str(bus), "rb", buffering=0)
      self.fw = io.open("/dev/i2c-"+str(bus), "wb", buffering=0)
      # set device address
      fcntl.ioctl(self.fr, I2C_SLAVE, device)
      fcntl.ioctl(self.fw, I2C_SLAVE, device)
   def write(self, bytes):
      self.fw.write(bytes)
   def read(self, bytes):
      return self.fr.read(bytes)
   def close(self):
      self.fw.close()
      self.fr.close()

我不知道,使用 C#,如何处理打开的文件 还向所述文件发送 ioctl 命令。我假设我会使用普通的FileStream 打开文件进行读写。到目前为止,我所拥有的只是使用 C 标准库的声明,如下所示:

public class IoCtl
{
    [DllImport("libc", EntryPoint = "ioctl", SetLastError = true)]
    private static extern int Command(int descriptor, UInt32 request, IntPtr data);

    // Equivalent of fcntl.ioctl()?

    // Write?

    // Read?

    // What happens with disposing the file? Do I need to write a destructor?
}

所以我有两个问题:

  • 如何正确实现文件访问with ioctl 使用 C#?
  • 关闭/处置使用ioctl 的所述文件的程序是什么?还是通常的using 声明?

【问题讨论】:

    标签: c# python linux mono ioctl


    【解决方案1】:

    Mono 提供对 ioctl、本机文件描述符、锁等的访问。通过 Mono.Unix.Native 命名空间,添加对 Mono.Posix 程序集的引用以访问它。

    我这里是凭记忆拍摄的,所以如果你想使用 Syscall.fcntl、Syscall.read、Syscall.write,你可能(将)需要填写实现:

    *nixy 的做法:

    class i2c
    {
        const int I2C_SLAVE = 0x0703;
        const int I2C_SLAVE_FORCE = 0x0706;
    
        int fd_write;
        int fd_read;
        string i2c_bus_file;
    
        public i2c (int device, String bus)
        {
            i2c_bus_file = String.Format ("/dev/i2c-{0}", bus);
            fd_write = Syscall.open (i2c_bus_file, OpenFlags.O_WRONLY, FilePermissions.DEFFILEMODE);
            // need to check Syscall.GetLastError()
            fd_read = Syscall.open (i2c_bus_file, OpenFlags.O_RDONLY, FilePermissions.DEFFILEMODE);
            // need to check Syscall.GetLastError()
    
            // I2C_SLAVE or I2C_SLAVE_FORCE if already in use...
            Syscall.fcntl (fd_read, I2C_SLAVE, device);
            // need to check Syscall.GetLastError()
            Syscall.fcntl (fd_write, I2C_SLAVE, device);
            // need to check Syscall.GetLastError()
        }
    
        public Errno write (byte[] data)
        {
            Syscall.write (fd_write, data, data.Length); 
            return Syscall.GetLastError ();
        }
    
        public Errno read (ref byte[] data)
        {
            Syscall.read (fd_read, data, data.Length);
            return Syscall.GetLastError ();
        }
    
        public void close ()
        {
            Syscall.close (fd_write);
            Syscall.close (fd_read);
        }
    }
    

    C#-ish 方式,是这样的吗? ;-)

        public FileStream getI2CStream(byte address, String bus)
        {
            var i2c_bus_file = String.Format ("/dev/i2c-{0}", bus);
            FileStream result = File.Open(i2c_bus_file, FileMode.Open);
            Syscall.fcntl(result.SafeFileHandle.DangerousGetHandle().ToInt32(), address);
            return result;
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-11-12
      • 1970-01-01
      • 2016-02-01
      • 2012-11-07
      • 2015-10-31
      • 1970-01-01
      • 2011-09-04
      相关资源
      最近更新 更多