From: | Kurt Harriman <harriman(at)acm(dot)org> |
---|---|
To: | pgsql-hackers(at)postgresql(dot)org |
Subject: | Mostly Harmless: Welcoming our C++ friends |
Date: | 2008-12-05 08:27:25 |
Message-ID: | [email protected] |
Views: | Whole Thread | Raw Message | Download mbox | Resend email |
Thread: | |
Lists: | pgsql-hackers |
Hi,
Sometimes people would like to call C++ code in the PostgreSQL
backend environment... for example, in user-defined functions,
triggers, access methods. And there is sometimes a need for
C++ code to call back into PostgreSQL's C functions, such as
the SPI interface. Many useful software packages and
libraries are written in C++.
The attached series of 4 es is meant to provide a minimal
level of support for C++ aficionados to easily compile and link
with the PostgreSQL backend. No new interfaces or wrappers are
provided. The goal is merely to make the backend a friendlier
place for developing extensions involving C++, with minimal
impact on the existing C code.
The proposed change is divided into 4 es with the hope
that each will be simple and easy to review. They can be
reviewed and discussed independently, and I hope some or
all may be judged benign enough to be taken up into 8.5 or
earlier.
The es are described in more detail below. They are:
1. c++reserved -- changes a few field and parameter
names which happened to be C++ reserved words
2. c++bookends -- adds C linkage declarations to a
few header files
3. c++configure -- adds C++ support to 'configure',
'make', and 'pg_config'. A new configure option
--enable-cplusplus links the C++ runtime library
in to the postgres backend.
4. c++exception -- converts unhandled C++ exceptions to
PostgreSQL elog(FATAL) errors
Regards,
... kurt
These es are based on CVS head in which the latest commit was
user: petere
date: Thu Dec 04 17:51:28 2008 +0000
summary: Default values for function arguments
1. c++reserved
User-defined functions and extensions may need to access
backend data structures such as parse trees. A few of the
relevant header files contain field or parameter names
which happen to be C++ reserved words. This makes them
unusable from C++ because the compiler chokes on the
reserved word. It has been suggested that the C++ user
could surround these #includes with #defines to substitute
innocuous words for the reserved words; but that would be
unbearably kludgy, error prone and unmaintainable. A polite
host does not demand such things of a guest.
Fortunately, there are not many instances which are likely
to be encountered by our C++ guests, and these can easily
be changed. In memnodes.h, parsenodes.h, and primnodes.h,
this changes the following field names:
typename => typeName
typeid => typeOid
using => usingClause
delete => delete_context
Also, the changes a few parameter names in function
s in makefuncs.h, parse_type.h, and builtins.h:
typename => typeName
typeid => typeOid
namespace => qualifier
There's no need to ask PostgreSQL developers to remember to
avoid C++ reserved words, because C++ users who are affected
by such occurrences can be asked to submit a corrective .
2. c++bookends
C++ code can call C functions and share global variables with C,
provided those declarations are surrounded by "bookends":
extern "C" {
...
};
Header files can be made bilingual, to declare interfaces which
look the same to both C and C++ callers. This is done by
placing C++ bookends within the header file, guarded by #ifdefs
#ifdef __cplusplus
extern "C" {
#endif
...
#ifdef __cplusplus
}; /* extern "C" */
#endif
This way the C++ caller can just #include the header file without
worrying whether the interface is implemented in C or C++.
Usually, extension modules written in C++ will put bookends around
all of their PostgreSQL #includes.
However, "postgres.h" usually stands alone as the first #include,
followed by some system #includes, and then the rest of the
PostgreSQL #includes. It is much nicer if a C++ file has just one
pair of bookends around its main block of PostgreSQL #includes.
This gives postgres.h its own internal bookends, making it
bilingual, so that its #include can continue to stand alone at the
head of each file.
Just a few additional header files are mentioned in the PostgreSQL
Reference Manual for add-on developers to use: fmgr.h, funcapi.h,
and spi.h. This adds bookends within those three files for
the benefit of beginners writing very simple extensions in C++.
Documentation and learning are simplified because C example code
can be compiled as C or C++ without change.
3. c++configure
This adds C++ support to the PostgreSQL build system.
After you have applied the , cd to the top of the source
tree (to the directory containing the file 'configure.in') and
execute these two commands to regenerate the 'configure' script
and some related files:
autoconf
autoheader
Much as it already does for the C compiler, the 'configure' script
will try to find the C++ compiler and set up appropriate command
line options. If 'configure' finds a C++ compiler, it will set up
src/Makefile.global to define the following makefile variables:
CXX = command for invoking C++ compiler
CXXCPP = command for invoking C++ preprocessor
CXXFLAGS = C++ compiler options
GXX = 'yes' if the C++ compiler is gcc/g++
Implicit rules are defined so that gmake will automatically invoke
the C++ compiler using the above variables given a source file name
suffixed with '.cpp' or '.cc'. So, to add a file named marvin.cpp
to the build, just add 'marvin.o' to the OBJS list in the Makefile.
To C++-compile a file with '.c' suffix, the Makefile should list
the .o file in both OBJS and CXXOBJS.
The pg_config utility can be used to display the CXX and CXXFLAGS.
Most C++ code typically uses some C++ features whose implementation
makes use of the compiler's runtime library: exceptions, static
constructors, new/delete, STL containers, stream I/O, etc. Specify
the following 'configure' option to link the C++ runtime library
into the postgres backend:
--enable-cplusplus
If --enable-cplusplus is specified, the makefile variable
'enable_cplusplus' will be set to 'yes', and pg_config.h will
#define ENABLE_CPLUSPLUS.
To ensure that the C++ runtime library is properly initialized,
on some platforms it is necessary for the main() function to be
compiled as C++. Therefore, if --enable-cplusplus is configured,
src/backend/main/main.c will be compiled as C++. This is
handled by the following lines in src/backend/main/Makefile:
ifeq ($(enable_cplusplus),yes)
CXXOBJS = main.o
endif
Fortunately, main.c can be compiled as either C or C++ with no
difficulty after applying the c++reserved and c++bookends
es. To make main.c bilingual, all that was needed was
a pair of bookends around its #includes.
Limitations:
- I haven't added support for profiling and code coverage for
C++. Automatic dependency generation is supported, however.
- This ought to work on platforms which use GCC, and maybe some
others. The only one I have tested is x86_32 Linux with GCC
4.1.2. Hopefully some interested hackers will try it on
platforms to which they have access, and post the results.
4. c++exception
When C code calls C++ code, all C++ exceptions need to be caught
and fully contained within the C++ code. Exceptions should never
be thrown outward across the C/C++ frontier.
If an exception is not caught within C++ code, and the search for
a matching 'catch' bumps into a C stack frame, the result may be
platform dependent. On my platform (Linux/GCC), if this happens
in the postgres backend, the process terminates silently as if
abort() had been called.
With this , if --enable-cplusplus is configured,
PostgresMain defines a handler to intercept any uncaught C++
exception and convert it to a conventional PostgreSQL error of
FATAL severity. This allows the backend to clean up and report
the error before terminating.
Attachment | Content-Type | Size |
---|---|---|
c++reserved. | text/plain | 47.4 KB |
c++bookends. | text/plain | 2.0 KB |
c++configure. | text/plain | 13.5 KB |
c++exception. | text/plain | 3.3 KB |
From | Date | Subject | |
---|---|---|---|
Next Message | Greg Smith | 2008-12-05 08:39:48 | Re: contrib/pg_stat_statements 1202 |
Previous Message | Greg Smith | 2008-12-05 08:26:47 | Re: [] pg_upgrade script for 8.3->8.4 |