Writing portable C header files can be difficult, since they may be read by different types of compilers:
extern "C"
directive, so that the
names aren't mangled. See section Writing libraries for C++, for other issues relevant
to using C++ with libtool.
#include
d.
These complications mean that your library interface headers must use some C preprocessor magic in order to be usable by each of the above compilers.
`foo.h' in the `demo' subdirectory of the libtool distribution serves as an example for how to write a header file that can be safely installed in a system directory.
Here are the relevant portions of that file:
/* __BEGIN_DECLS should be used at the beginning of your declarations, so that C++ compilers don't mangle their names. Use __END_DECLS at the end of C declarations. */ #undef __BEGIN_DECLS #undef __END_DECLS #ifdef __cplusplus # define __BEGIN_DECLS extern "C" { # define __END_DECLS } #else # define __BEGIN_DECLS /* empty */ # define __END_DECLS /* empty */ #endif /* __P is a macro used to wrap function prototypes, so that compilers that don't understand ANSI C prototypes still work, and ANSI C compilers can issue warnings about type mismatches. */ #undef __P #if defined (__STDC__) || defined (_AIX) \ || (defined (__mips) && defined (_SYSTYPE_SVR4)) \ || defined(WIN32) || defined(__cplusplus) # define __P(protos) protos #else # define __P(protos) () #endif
These macros are used in `foo.h' as follows:
#ifndef _FOO_H_ #define _FOO_H_ 1 /* The above macro definitions. */ ... __BEGIN_DECLS int foo __P((void)); int hello __P((void)); __END_DECLS #endif /* !_FOO_H_ */
Note that the `#ifndef _FOO_H_' prevents the body of `foo.h' from being read more than once in a given compilation.
Feel free to copy the definitions of __P
, __BEGIN_DECLS
,
and __END_DECLS
into your own headers. Then, you may use them to
create header files that are valid for C++, ANSI, and non-ANSI
compilers.
Do not be naive about writing portable code. Following the tips given above will help you miss the most obvious problems, but there are definitely other subtle portability issues. You may need to cope with some of the following issues:
void *
generic
pointer type, and so need to use char *
in its place.
const
and signed
keywords are not supported by some
compilers, especially pre-ANSI compilers.
long double
type is not supported by many compilers.
Go to the first, previous, next, last section, table of contents.