Ch11.16: Wine File APIs

Overview

Wine (“Wine Is Not an Emulator”) lets Windows binaries run on POSIX systems such as Linux and FreeBSD. Wine implements the Win32 and NT APIs by translating them into host system calls — and those host system calls ultimately use POSIX file descriptors.

When fast_io is built as part of Wine itself (or for code running under Wine that needs to talk to the host directly), it exposes this layer through:

Note: The Wine layer is not yet finished in upstream fast_io. This section describes the design as it is intended to land. The concepts, however, follow exactly the same RAII / observer pattern you have already seen for POSIX, Win32, and NT.

The Pattern Is the Same

Every layer in fast_io follows the same shape:

  1. An owning RAII type named xxx_file.
  2. A non-owning observer type named xxx_io_observer.
  3. Full support for print, println, and scan.
  4. The ability to wrap raw handles from outside code.

wine_file is no exception. Conceptually it looks like this:


#include <fast_io.h>
#include <fast_io_device.h>

int main()
{
    using namespace ::fast_io::iomnp;

    // Opens a file through the Wine host layer.
    ::fast_io::wine_file wf(u8"hello_wine.txt", ::fast_io::open_mode::out);

    println(wf, u8"Hello from wine_file!");

    ::std::size_t const n{42zu};
    println(wf, u8"The answer is: ", n);
}
      

Wrapping a Wine Host File Descriptor

When Wine translates a Windows CreateFileW call, it eventually produces a host POSIX file descriptor. You can wrap that descriptor in a wine_io_observer to continue working with it through fast_io:


#include <fast_io.h>
#include <fast_io_device.h>

void write_via_wine(int host_fd)
{
    using namespace ::fast_io::iomnp;

    // Non-owning view over Wine's host fd.
    ::fast_io::wine_io_observer observer{
        static_cast<::fast_io::wine_io_observer::native_handle_type>(host_fd)};
    println(observer, u8"Written through a wine_io_observer\n");
}
      

Why Does This Layer Exist?

Wine is a complex piece of infrastructure. Code that lives inside Wine (for example, Wine's own implementation of ntdll.dll or kernel32.dll) needs to:

wine_file gives Wine developers the same RAII / observer ergonomics they get from the other layers, without having to write manual resource management for every call site.

Relationship to the Other Layers

On a POSIX host running Wine, the full layering looks like this:

So from the guest's point of view, the I/O went through the NT layer. From the host's point of view, it went through POSIX. wine_file lives at the seam between the two.

Summary