On Wed, Jun 02, 2010 at 10:11:37AM +0800, Craig Ringer wrote: > On 02/06/10 09:23, Bruce Momjian wrote: > > Tom Lane wrote: > >> Craig Ringer <craig@xxxxxxxxxxxxxxxxxxxxx> writes: > >>> On 01/06/10 11:05, Tom Lane wrote: > >>>> I'd be interested to see a section like this written by someone who'd > >>>> actually done a nontrivial C++ extension and lived to tell the tale. > >> > >>> I can't speak up there - my own C++/Pg backend stuff has been fairly > >>> trivial, and has been where I can maintain a fairly clean separation of > >>> the C++-exposed and the Pg-backend-exposed parts. I was able to keep > >>> things separate enough that my C++ compilation units didn't include the > >>> Pg backend headers; they just exposed a pure C public interface. The Pg > >>> backend-using compilation units were written in C, and talked to the C++ > >>> part over its exposed pure C interfaces. > >> > >> Yeah, if you can design your code so that C++ never has to call back > >> into the core backend, that eliminates a large chunk of the pain. > >> Should we be documenting design ideas like this one? > > > > I have incorporated the new ideas into the C++ documentation section, > > and removed the comment block in the attached patch. > > If you're going to include that much, I'd still really want to warn > people about exception/error handling too. It's important. I made brief > mention of it before, but perhaps some more detail would help if people > really want to do this. > > ( BTW, all in all, I agree with Tom Lane - the best answer is "don't". > Sometimes you need to access functionality from C++ libraries, but > unless that's your reason I wouldn't ever consider doing it. ) > > Here's a rough outline of the rules I follow when mixing C/C++ code, > plus some info on the longjmp error handling related complexities added > by Pg: > > > > Letting an exception thrown from C++ code cross into C code will be > EXTREMELY ugly. The C++-to-C boundaries *must* have unconditional catch > blocks to convert thrown exceptions into appropriate error codes, even > if the C++ code in question never knowingly throws an exception. C++ may > throw std::bad_alloc on failure of operator new(), among other things, > so the user must _always_ have an unconditional catch. Letting an > exception propagate out to the C-based Pg backend is rather likely to > result in a backend crash. > > If the C++ libraries you are using will put up with it, compile your C++ > code with -fno-exceptions to make your life much, much easier, as you > can avoid worrying about this entirely. OTOH, you must then check for > NULL return from operator new(). > > If you can't do that: My usual rule is that any "extern C" function > *must* have an unconditional catch. I also require that any function > that may be passed as a function pointer to C code must be "extern C" > and thus must obey the previous rule, so that covers function pointers > and dlopen()ed access to functions. > > > > > Similarly, calling Pg code that may use Pg's error handling from within > C++ is unsafe. It should be OK if you know for absolute certain that the > C++ call tree in question only has plain-old-data (POD) structs and > simple variables on the stack, but even then it requires caution. C++ > code that uses Pg calls can't do anything it couldn't do if you were > using 'goto' and labels in each involved function, but additionally has > to worry about returning and passing non-POD objects between functions > in a call chain by value, as a longjmp may result in dtors not being > properly called. > > The best way to get around this issue is not to call into the Pg backend > from C++ code at all, instead encapsulating your C++ functionality into > cleanly separated modules with pure C interfaces. If you don't #include > any Pg backend headers into any compilation units compiled with the C++ > compiler, that should do the trick. > > If you must mix Pg calls and C++, restrict your C++ objects to the heap > (ie use pointers to them, managed with new and delete) and limit your > stack to POD variables (simple structs and built-in types). Note that > this means you can't use std::auto_ptr, std::tr1:shared_ptr, RAII lock > management, etc in C++ code that may call into the Pg backend. Is PostGIS following these guidelines? Cheers, David. -- David Fetter <david@xxxxxxxxxx> http://fetter.org/ Phone: +1 415 235 3778 AIM: dfetter666 Yahoo!: dfetter Skype: davidfetter XMPP: david.fetter@xxxxxxxxx iCal: webcal://www.tripit.com/feed/ical/people/david74/tripit.ics Remember to vote! Consider donating to Postgres: http://www.postgresql.org/about/donate -- Sent via pgsql-general mailing list (pgsql-general@xxxxxxxxxxxxxx) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-general