How to compile, link and use a C++ extension

Started by jacques kleinover 10 years ago7 messages
#1jacques klein
jacques.klei@googlemail.com

Hello, I want to write a "BackgroundWorker" in C++ (have lots of C++
code and libs to reuse).

I found " 35.9.13 Using C++ for Extensibility " in the 9.3/4
documentation who says it's possible and gives some guidelines for
source-code writing.
Compiling is not too difficult if one understands this chapter.

However I coudn't find any doc. about how to solve the problem of
linking C++ code and libs into the .so of my extension,
and nothing to solve the runtime-loading problem of the c++ specific .so
files ( for ex. to make work a simple usage std::string )

I started my tests by cloning the contrib/worker_spi code, and when
transforming the code into C++, I could only note that C++ is not
supported in the provided Makefiles.

I also found some rather old (2008) message in this mailing list which
addresses the same subject:
/messages/by-id/4938E5ED.60102@acm.org:
Mostly Harmless: Welcoming our C++ friends
with patches that didn't reach their way into the source-distrib , I guess.

Is there something more actual about this subject that could help ?.

Jacques K.

#2Andres Freund
andres@anarazel.de
In reply to: jacques klein (#1)
Re: How to compile, link and use a C++ extension

Hi,

On 2015-08-14 18:38:36 +0200, jacques klein wrote:

However I coudn't find any doc. about how to solve the problem of linking
C++ code and libs into the .so of my extension,
and nothing to solve the runtime-loading problem of the c++ specific .so
files ( for ex. to make work a simple usage std::string )

libstdc++ (or whatever your platform uses) should be automatically
loaded, I don't think you'll need to worry about that.

I started my tests by cloning the contrib/worker_spi code, and when
transforming the code into C++, I could only note that C++ is not supported
in the provided Makefiles.

Yes, that doesn't surprise me. Postgres itself doesn't need to care
about looking for a usable C++ compiler et al.

How exactly do you need to use the C++ code? The easiest probably would
be to have a separate object file, built using your own makefile rule,
that contains a the C++ and provides a C interface, and then use that
from a background worker purely written in C.

Greetings,

Andres Freund

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#3Tom Lane
tgl@sss.pgh.pa.us
In reply to: Andres Freund (#2)
Re: How to compile, link and use a C++ extension

Andres Freund <andres@anarazel.de> writes:

On 2015-08-14 18:38:36 +0200, jacques klein wrote:

However I coudn't find any doc. about how to solve the problem of linking
C++ code and libs into the .so of my extension,
and nothing to solve the runtime-loading problem of the c++ specific .so
files ( for ex. to make work a simple usage std::string )

libstdc++ (or whatever your platform uses) should be automatically
loaded, I don't think you'll need to worry about that.

Yeah. The painful issues you're going to face are not that. They are
memory management (C++ "new" does not talk to palloc or vice versa)
and error handling ("throw" does not interoperate with PG_TRY()).

If you can build a bulletproof interface layer between your C++ code and
the surrounding C-coded backend, you can make it work, but that part won't
be any fun. There's way too much temptation to just call assorted C-coded
functions from your C++, and *that won't work* with any reliability.

There are discussions of these issues in the pgsql-hackers archives.

regards, tom lane

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#4Peter Geoghegan
pg@heroku.com
In reply to: Tom Lane (#3)
Re: How to compile, link and use a C++ extension

On Fri, Aug 14, 2015 at 10:28 AM, Tom Lane <tgl@sss.pgh.pa.us> wrote:

Yeah. The painful issues you're going to face are not that. They are
memory management (C++ "new" does not talk to palloc or vice versa)
and error handling ("throw" does not interoperate with PG_TRY()).

It's worse than that. Any use of longjmp() will cause undefined
behavior in C++. That's because each C++ object's destructor will not
be called (possibly other reasons, too).

I suggest looking at the PL/V8 code for an example of how to make C++
code work as a Postgres extension. IIRC they've made specific
trade-offs that might be useful for Jacques' use case too.

--
Peter Geoghegan

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#5Andres Freund
andres@anarazel.de
In reply to: Peter Geoghegan (#4)
Re: How to compile, link and use a C++ extension

On 2015-08-14 11:10:14 -0700, Peter Geoghegan wrote:

On Fri, Aug 14, 2015 at 10:28 AM, Tom Lane <tgl@sss.pgh.pa.us> wrote:

Yeah. The painful issues you're going to face are not that. They are
memory management (C++ "new" does not talk to palloc or vice versa)
and error handling ("throw" does not interoperate with PG_TRY()).

It's worse than that. Any use of longjmp() will cause undefined
behavior in C++. That's because each C++ object's destructor will not
be called (possibly other reasons, too).

Only if that longjmp goes through C++ code with non-POD objects. Which
you should pretty much never allow.

- Andres

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#6Andrew Dunstan
andrew@dunslane.net
In reply to: Peter Geoghegan (#4)
Re: How to compile, link and use a C++ extension

On 08/14/2015 02:10 PM, Peter Geoghegan wrote:

On Fri, Aug 14, 2015 at 10:28 AM, Tom Lane <tgl@sss.pgh.pa.us> wrote:

Yeah. The painful issues you're going to face are not that. They are
memory management (C++ "new" does not talk to palloc or vice versa)
and error handling ("throw" does not interoperate with PG_TRY()).

It's worse than that. Any use of longjmp() will cause undefined
behavior in C++. That's because each C++ object's destructor will not
be called (possibly other reasons, too).

I suggest looking at the PL/V8 code for an example of how to make C++
code work as a Postgres extension. IIRC they've made specific
trade-offs that might be useful for Jacques' use case too.

Yeah, although be aware that PLv8 still has odd buggy behaviours that I
am not sure are not related to some C/C++ impedance mismatch.

cheers

andrew

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#7Craig Ringer
craig@2ndquadrant.com
In reply to: Andres Freund (#2)
Re: How to compile, link and use a C++ extension

On 15 August 2015 at 00:51, Andres Freund <andres@anarazel.de> wrote:

I started my tests by cloning the contrib/worker_spi code, and when
transforming the code into C++, I could only note that C++ is not supported
in the provided Makefiles.

Yes, that doesn't surprise me. Postgres itself doesn't need to care
about looking for a usable C++ compiler et al.

I think it'd be necessary to add C++ support to PGXS to do this nicely.

Because PostgreSQL's headers have C++

extern "C" {

wrappers in them, you could potentially compile the whole extension
g++, using "extern C" to expose unmangled symbols. You'll run into
some issues due to incompatible compiler flags, though:

$ PATH=$HOME/pg/95/bin:$PATH make USE_PGXS=1 CC=g++
g++ -Wall -Wmissing-prototypes -Wpointer-arith
-Wdeclaration-after-statement -Wendif-labels
-Wmissing-format-attribute -Wformat-security -fno-strict-aliasing
-fwrapv -fexcess-precision=standard -O2 -fpic -I. -I./
-I/home/craig/pg/95/include/postgresql/server
-I/home/craig/pg/95/include/postgresql/internal -D_GNU_SOURCE -c -o
worker_spi.o worker_spi.c
cc1plus: warning: command line option ‘-Wmissing-prototypes’ is valid
for C/ObjC but not for C++
cc1plus: warning: command line option ‘-Wdeclaration-after-statement’
is valid for C/ObjC but not for C++
cc1plus: sorry, unimplemented: -fexcess-precision=standard for C++
<builtin>: recipe for target 'worker_spi.o' failed
make: *** [worker_spi.o] Error 1

How exactly do you need to use the C++ code? The easiest probably would
be to have a separate object file, built using your own makefile rule,
that contains a the C++ and provides a C interface, and then use that
from a background worker purely written in C.

This is what I would advise too.

It helps to separate the PostgreSQL bits from the C++ bits, providing
a clean interface across which exceptions are not thrown.

It isn't safe to access PostgreSQL API from within your C++ code
anyway, so the C++ code can be compiled without any PostgreSQL
includes, exposing a pure C interface that your extension can then
link to as just another library via PGXS's SHLIB_LINK option.

--
Craig Ringer http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers