Mostly Harmless: Welcoming our C++ friends

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: 4938E5ED.60102@acm.org
Views: Raw Message | Whole Thread | 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 patches 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 patches 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 patches 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 patches 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 patch changes the following field names:

typename => typeName
typeid => typeOid
using => usingClause
delete => delete_context

Also, the patch changes a few parameter names in function
prototypes 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 patch.

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 patch 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 patch 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 patch adds C++ support to the PostgreSQL build system.

After you have applied the patch, 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
patches. 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 patch, 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.patch text/plain 47.4 KB
c++bookends.patch text/plain 2.0 KB
c++configure.patch text/plain 13.5 KB
c++exception.patch text/plain 3.3 KB

Responses

Browse pgsql-hackers by date

  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: [patch] pg_upgrade script for 8.3->8.4