Glib: a Win32 discussion
- From: Kean Johnston <kean johnston gmail com>
- To: gtk-devel-list gnome org
- Subject: Glib: a Win32 discussion
- Date: Wed, 06 Apr 2011 23:34:59 +0200
Everyone,
WARNING: long, detailed message. If you don't care about Win32, move on.
I would like to start a discussion on making changes to Glib for improved
Win32 support. These changes will eliminate many of the pitfalls that
usually accompany that platform, and better live up to the "mission
statement" of Glib (which isn't really a mission statement, but instead is
an indication to users of what it is trying to achieve - "It works on many
UNIX-like platforms, Windows, OS/2 and BeOS". These are just ideas, and I
appreciate any and all feedback.
Before even discussing the changes I'd like to propose, it is important to
discuss the actual problems the changes are trying to solve. I am not
making any changes just for change's sake. First and foremost of those
changes is the complete and total avoidance of the C runtime DLL,
msvcrt.dll. There are many good reasons for doing this. First, none of the
modern MS compilers allow you to directly target using msvcrt.dll (which is
present on all Windows systems) and instead force you to use
compiler-specific versions of the C runtime, which you then have the
obligation to either install yourself, or ensure are installed. It is
possible to craft a set of tools (using a mixture of the driver development
kit, platform development kit, Visual Studio and a large number of hacks)
that will allow modern MS compilers to target msvcrt.dll, but doing so is
extraordinarily complicated and one tiny mis-step along the way causes
things to fail in subtle ways. An alternative is to use and support only
MinGW and MSYS, and this is really tempting, except that using these tools
you can NOT avoid dependence on msvcrt.dll. There are severe limitations
imposed by using it, not least of which is the fact all file descriptors,
the heap and other information is local to each DLL. Unlike the UNIX world
where a shared object uses the same malloc as an application (under almost
all circumstances), an object created in one DLL cannot be freed by
another, or a file descriptor opened in one cannot be closed in another.
The only way to ensure this does not happen is to guarantee that every
single library you build with uses the exact same CRT, and that it is
shared. This is very difficult to achieve.
By avoiding the CRT altogether and using native Windows functions that use
handles, and using a memory allocator other than malloc, all of these
problems go away. Glib already makes this possible by providing its own
malloc wrappers, but the current Win32 implementation is the same as the
UNIX one in that it is just a very thin layer on top of malloc. The first
thing that should change is making g_malloc and friends use the HeapAlloc
function, and ensure that g_mem_is_system_malloc() always returns false.
This is really easy to do and shouldn't upset the apple-cart too much.
Memory allocation is the easy bit. HeapAlloc maps nicely onto malloc. There
are other bits that are more problematic. The next easiest to solve is
stat(). Gio already makes a token gesture at wrapping stat() but its
wrapping is a bit TOO thin. Not only is the stat structure problematic
under Windows, it is problematic under UNIX too, as many stat structures,
even directly out of sys/stat.h, change according to pre-processor defines
(LFS). Ideally, we should create a GStatBuf structure that is defined only
in terms of portable data types that are like-sized on all systems. We
should ensure that the file sizes are always 64 bits, and that the
timestamps are always 32-bits, using 1-1-1970 as the epoch (standard UNIX
time). Bonus points if we provide *both* 32 and 64-bit times. If we did
that, we would need to come to some agreement on exactly what a 64-bit time
represents. Then, we ensure that g_stat() always fills in GStatBuf with
whatever conversions are necessary, so that a unified interface is
presented to an application. This too, is very easy to do and shouldn't
upset the apple-cart too much, with the exception of 64-bit time stamps,
which, if people want to support, may take some hashing out. Wrapping stat
can also fix the problem of having the uid_t / gid_t types differ not only
from system to system, but also change on the SAME system depending on
defines. We can force these to always be 32-bit. Similarly, ino_t.
The biggest and most challenging thing I would like to propose is the
addition of gstdio. Currently there is no attempt to provide a portable
standard IO set of functions, and these are notorious for subtle
differences. For example, does snprintf() return the number of characters
that would be required if N were unlimited? We need not develop a stdio
package from scratch, not by any means, but can instead base it off glibc's
stdio, which is also LGPL'ed. We can modify the internals when necessary to
use glib functions (for example, use g_malloc instead of malloc). This
package can be easily modified to return a Glib-abstracted FILE structure
(GFILE). On systems where stdio is known to have a certain behaviour this
whole package can be a very thin wrapping, but the behaviour of all of the
functions should be identical on all platforms Glib supports. Obviously
fstat() would become g_fstat() and conform to the unified stat structure
mentioned above.
Last, but by no means least, is the reliance on "compiled" files, like
compiled schemas (or in the case of Gtk, icon caches). On UNIX systems
where things are installed in a universally-accessible location, this isn't
a problem, but on Win32, where multiple applications could all include
their own private copies of the DLL's, this is a problem. Fixing this is a
bit tricky but very doable. Windows does provide two places that are
predictable and universally accessible: the registry, and %ProgramData%.
The registry is a poor choice except perhaps for location files inside
%ProgramData%. The registry is slow, and also imposes some severe
limitations on key sizes etc. This can be very easily addressed by
compiling Glib with LIBDIR set to something like "%ProgramData%\Glib\2.x"
and ensuring that functions like g_file_get_contents() or g_open() all call
ExpandEnvironmentStrings() on Win32. This is also a relatively small change
and doesn't change any existing API's (although on Win32 it will have a
behaviour change).
I don't know if there has been a discussion on a Glib 3.0, but perhaps all
of this could be the basis for one (especially with the addition of
gstdio). I am volunteering to spear-head all of this work. I don't have
write access to anything but if there isn't already a 3.0 branch, and
people like / agree / support the above, perhaps we can change that and I
can start work.
One last thing, since it has proven to be a source of considerable
incompatibility, and that's the reliance on D-Bus. I think it should remain
possible to use dbus if you want it, if your application really needs it,
but to have relatively (from my position of ignorance) unrelated things
like gapplication absolutely rely on it is a mistake, as far as I can see.
dbus is really not appropriate for, or required for, many applications that
would otherwise want to use Glib/Gtk. Should my Windows MP3 editor really
need dbus daemons running just because it uses GtkApplication (which in
turn uses gio/glib and thus the dbus coupling)? Seems like a good bit of
gio could use some re-thinking and this again is maybe more appropriate for
a 3.0 release where we may be able to get away with slightly more
disruptive changes.
Thank you for your time reading this, and I welcome comments and debate.
Kean
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]