Chapter 4. Programming with Cygwin

Table of Contents

Using GCC with Cygwin
Standard Usage
Building applications for 64 bit Cygwin
GUI Mode Applications
Debugging Cygwin Programs
Building and Using DLLs
Building DLLs
Linking Against DLLs
Defining Windows Resources
Profiling Cygwin Programs
Introduction
Examples
Special situations
Profiling multi-threaded programs
Profiling programs that fork
Getting better profiling resolution
Profiling programs with their libraries
Profiling Cygwin itself

Using GCC with Cygwin

Standard Usage

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, World

bash$

Building applications for 64 bit Cygwin

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;
}

GUI Mode Applications

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.