Connecting I/O devices to file units

Is is it possible to connect devices like the keyboard, mouse, and others to file units?

For example imagine the mouse was connected to unit 40:

! mouse state
integer :: ix, iy   ! cursor position
integer :: kx, ky   ! scroll position
integer :: bstate   ! button states (bitmask)

read(40,*) ix, iy, kx, ky, bstate 

I was wondering if something like this might be possible using anonymous pipes or mapped memory?

It’s always possible to defer this to a library routine implemented in whatever way,

call read_mouse(...)

but in some circumstances it would be nice to preserve the Fortran I/O abstraction.

1 Like

Don’t know about Windows but on Linux you might be able to do the Fortran equivalent of the C code discussed here:

On Linux, you have a character device (special file) /dev/input/mouse0. You need root privileges (or input group membership) to read it. It actually emits some data when the mouse is moved or clicked but the format of those data is (to me) unknown. Still, I doubt Fortran is the right tool for that, I guess the idea of non-blocking read is something not known to Fortran. Besides, if you mean any GUI environment like X11, it is all event-driven, not very fortranly either.

So probably the best way to go would be to interface some C+X11 code, see e.g. this link. It also mentions a utility, xinput which can report events and, maybe write the output to a pipe read by Fortran code. Still there will be an issue to deal with blocking read when no new event arrives.

Edit: maybe ASYNCHRONOUS could be the answer but I have no experience with that modern feature of Fortran

The C code to read the mouse in the following link might also work for Fortran but as @msz59 points out you would probably need to run under sudo. I also agree its probably best just to create a C or C++ utility (or find one in an existing library) than try to read either the mouse or the keyboard directly in Fortran.

I dream of an API to register a custom handler to a file unit, to read from/write to a socket, a message queue, the syslog, or as you say an anonymous pipe or mapped memory.

The code would call read(40 ,*) or write(40, *), and, depending on what has been associated with 40, the I/O could end up anywhere, not necessarily a file on disk.

This could also be a logging mechanism: associate 1 with “critical logs”, 6 with “debug logs”, and depending on the user configuration, associate 6 to stdout or to a do-nothing callback.

That would be an incredible abstraction. My Fortran applications are general purpose, with a lot of logging, dialog with devices, etc. (and almost no math), and having this would be very appreciable.

With gfortran, and a good deal of hacking, this is actually possible: the libgfortran shared library exposes a _gfortrani_get_unit that allows to retrieve, and modify, the read/write/seek/… callbacks structure associated with any file unit (the stream_vtable structure). Of course, I strongly discourage doing such thing! But it shows the underlying compiler architecture would allow an API to connect a custom handler to a file unit.

1 Like