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:[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.



AttachmentContent-TypeSize
c++reserved.text/plain47.4 KB
c++bookends.text/plain2.0 KB
c++configure.text/plain13.5 KB
c++exception.text/plain3.3 KB

Responses

Browse pgsql-hackers by date

 FromDateSubject
Next MessageGreg Smith2008-12-05 08:39:48Re: contrib/pg_stat_statements 1202
Previous MessageGreg Smith2008-12-05 08:26:47Re: [] pg_upgrade script for 8.3->8.4