Writing Portable C
Helpful conditional includes, macros and routines for porting Unix applications to Windows, while maintaining existing portability on Linux and freeBSD.
[Download here]
Author Jon A. Lambert
Date 12/16/2005
Version 0.5
Copyright 2002 - all rights reserved.
Released under Mesh Public License
All other authors credits and licenses included in source sections separated by hyphens.
General considerations
- Define WIN32 and WIN32_LEAN_AND_MEAN in your windows makefiles.
- Most of the normal system header includes are done here so you will want to remove them from the application source files and include os.h.
- We'd use configure and autotools but we don't have them. So you need to run configure on the application using a unix-like system before porting.
- Avoid the use of open, read, write, and close on files. These can be converted to fopen, fread, fwrite, and fclose. We redefine close on Windows to closesocket.
- Add the binary option to all file open routines regardless of whether the file is text or binary. "r" -> "rb", "w" -> "wb", etc.
- You have to deal with fork, vfork, alarm and signal handling on your own. It's not all that difficult depending on it's purpose.
Network considerations
- read and write on sockets should be converted to send and recv.
- macros WIN32STARTUP and WIN32CLEANUP should be called once at the beginning of the application and at the exit respectively. This means you will place WIN32CLEANUP at every possible exit point of the application.
- Use macro GETERROR everywhere errno is used in sockets functions.
- Use INVALID_SOCKET macro to check result of socket and accept. Negative socket values are legal on Windows.
- Use SOCKET_ERROR to check for error conditions on all other return conditions of network socket functions.
- Use SOCKET to refer to sockets because they are signed on Unix, unsigned on Windows.
- Pay careful attention to the logical used of counting and comparing file descriptors returned by socket, accept and used as first parameter of select. Windows socket descriptors are random assigned, not sequentially assigned.
Various Macros
- OS_RAND and OS_SRAND should be used in place of rand, random, srand, and srandom
- many other macros that allow the transparent use of index, strcasecmp, strncasecmp, bcopy, bcmp, bzero, etc.
Supplied routines
- FGETS is a replacement for fgets that handles text files that use \n as the line terminator. The presumption being files are opened in binary mode and not converted.
- re_comp and re_exec are supplied for Visual C and LCC compilers. This is a low functionality replacement.
- opendir, closedir, and readdir are supplied for Visual C and LCC compilers.
- crypt is supplied which is compatible with linux crypt.
Other notes
- popen and pclose aren't available on Digital Mars.
- gdbm, dbm, ndbm and getopt Windows ports are bundled separately as they are under GPL. See MudPortsProject.
- Sample makefiles for different compilers are included. These are from the PernMush? port. These have various levels of support for multiple configurations, static or dynamic linking, linking to debug or non-debug libraries, auto-generated dependencies, distribution targets, etc.
Makefile - Cygwin, Linux and FreeBSD (using gmake)
Makefile.bor - Borland Builder 5.3 or the Borland C/C++ 5.5 (free compiler)
Makefile.vc - Visual C 6.0, 7.0 and 7.1
Makefile.lcc - Logiciels/Informatique (lcc-win32) C compiler
Makefile.dgm - Digital Mars C/C++