使用Mono和P / Invoke处理文件句柄

时间:2015-12-29 21:45:06

标签: c# python linux mono ioctl

我有一些最初用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?
}

所以我有两个问题:

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

1 个答案:

答案 0 :(得分:2)

Mono通过Mono.Unix.Native命名空间提供对ioctl,本机文件描述符,锁等的访问。添加对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;
    }