Chapter 4. Programming with Cygwin
Prev |  | Next

# Chapter 4. Programming with Cygwin

## 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.

Prev |  | Next
Using Cygwin effectively with Windows | Home | Debugging Cygwin Programs