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:
-
::fast_io::wine_file— an RAII owning wrapper over a Wine host file descriptor. -
::fast_io::wine_io_observer— a non-owning view over an existing Wine host file descriptor.
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:
- An owning RAII type named
xxx_file. - A non-owning observer type named
xxx_io_observer. - Full support for
print,println, andscan. - 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:
-
Receive a Windows
HANDLEfrom guest code. -
Translate it into a host
int fdvia Wine's internal table. -
Perform host I/O on that
fdwhile still being able to surface errors back to the guest as NTSTATUS codes.
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:
-
A guest Windows binary calls
WriteFile. That resolves, inside Wine, tontdll!NtWriteFile. -
Wine's
ntdlltranslates that to a host POSIXwrite(2)call on a host fd — and that fd is whatwine_filewraps.
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
-
::fast_io::wine_fileis the RAII wrapper for Wine host file descriptors. -
::fast_io::wine_io_observeris the non-owning view. -
The Wine layer is still a work in progress, but its design follows the exact
same pattern as
posix_file,win32_file, andnt_file. - It lives at the boundary between a Windows guest and the POSIX host that Wine runs on.