Table of Contents
Use gcc to compile, just like under UNIX. Refer to the GCC User's Guide for information on standard usage and options. Here's a simple example:
Example 4.1. Building Hello World with GCC
bash$
gcc hello.c -o hello.exe
bash$
hello.exe
Hello, Worldbash$
The 64 bit Cygwin toolchain uses the Microsoft x64 calling convention by default, so you can create applications using the Win32 API just as with the 32 bit Cygwin toolchain.
There's just one important difference. The 64 bit Cygwin compilers use a different data model than the Mingw and Microsoft compilers. For reference, see the Wikipedia entry on 64-bit computing.
While the Mingw and Microsoft compilers use the LLP64
data model, Cygwin compilers use the LP64
data model, just
like Linux. This affects the size of the type long
. In the
LLP64
model preferred by Microsoft,
sizeof(long)
is 4. This applies for the related Win32
types like LONG
, ULONG
,
DWORD
, etc., too.
In the LP64
model used by Cygwin, sizeof(long)
is 8,
just like the size of pointers or the types size_t/ssize_t
.
This simplifies porting Linux applications to 64 bit Cygwin, but it requires
due diligence when calling Windows functions taking LONG, ULONG, DWORD, or any
other equivalent type. This is especially important in conjunction with
pointers.
Here's an example. The Win32 function ReadFile
returns the number of read bytes via a pointer to a DWORD variable:
BOOL WINAPI ReadFile (HANDLE, PVOID, DWORD, PDWORD, LPOVERLAPPED);
Note that the forth parameter is a pointer to a DWORD, thus it's a
pointer to a 4 byte type, on 32 as well as on 64 bit Windows. Now we write
our own my_read
function using ReadFile:
Example 4.2. 64bit-programming, Using ReadFile, 1st try
ssize_t my_read (int fd, void *buffer, size_t bytes_to_read) { HANDLE fh = _get_osfhandle (fd); ssize_t bytes_read; if (ReadFile (fh, buffer, bytes_to_read, (PDWORD) &bytes_read, NULL)) return bytes_read; set_errno_from_get_last_error (); return -1; }
While this example code works fine on 32 bit Windows, it has in fact
a bad bug. The assumption that the size of ssize_t is the same as the size
of DWORD is wrong for 64 bit. In fact, since
sizeof(ssize_t)
is 8, ReadFile
will write the number of read bytes into the lower 4 bytes of the variable
bytes_read
, while the upper 4 bytes will contain an
undefined value. my_read
will very likely return the
wrong number of read bytes to the caller.
Here's the fixed version of my_read
:
Example 4.3. 64bit-programming, Using ReadFile, 2nd try
ssize_t my_read (int fd, void *buffer, size_t bytes_to_read) { HANDLE fh = _get_osfhandle (fd); DWORD bytes_read; if (ReadFile (fh, buffer, bytes_to_read, &bytes_read, NULL)) return (ssize_t) bytes_read; set_errno_from_get_last_error (); return -1; }
Cygwin comes with an X server, so usually you should compile your GUI applications as X applications to allow better interoperability with other Cygwin GUI applications.
Other than that, Cygwin allows you to build programs with full access to the standard Windows API, including the GUI functions as defined in any Microsoft or off-the-shelf publication.
The build process is similar to any other build process. The only difference is that you use gcc -mwindows to link your program into a GUI application instead of a command-line application. Here's an example Makefile:
myapp.exe : myapp.o myapp.res gcc -mwindows myapp.o myapp.res -o $@ myapp.res : myapp.rc resource.h windres $< -O coff -o $@
Note the use of windres
to compile the
Windows resources into a COFF-format .res
file.
That will include all the bitmaps, icons, and other resources you
need, into one handy object file. For more information on
windres
, consult the Binutils manual.