Tom Lane schrob: > Kevin Murphy <murphy@xxxxxxxxxxxxxxx> writes: >> Tom Lane wrote: >>> I think he needs to rewrite in C :-(. The backend is not C++ and I >>> fear it's unlikely that libc++ will play nicely as a dynamic add-on. > >> It would be great if some C++/C guru could make a thorough analysis of >> C++ integration issues. > > The main thing that scares me is lack of integration of C error handling > (setjmp/longjmp) with C++ error handling (catch/throw). In a > self-contained module you could perhaps avoid this by not using > catch/throw, but I don't think you get to ignore the issue if you are > using STL modules. > > It *might* work to put a generic "catch/report via elog" handler around > each one of your entry-point functions. Haven't tried it. Hmm, this setup worked quite stable here for some smaller educational projects. The snippet I used to wrap the C++ was: --8<---------------cut here---------------start------------->8--- #include <stdexcept> extern "C" { #include <postgres.h> #include <fmgr.h> } extern "C" { PG_FUNCTION_INFO_V1(cpptest); Datum cpptest(PG_FUNCTION_ARGS); } Datum cpptest(PG_FUNCTION_ARGS) { try { throw std::runtime_error("Your code here."); } catch (std::exception &e) { elog(ERROR, "caught C++ exception: %s", e.what()); } catch (...) { elog(ERROR, "caught non-standard C++ exception."); } } --8<---------------cut here---------------end--------------->8--- I was even able to spare the exception code and the extern "C"s in each and every function by hacking together a language handler loading functors (classes overloading the operator "()") using the class loader documented in this paper: <http://www.s11n.net/papers/classloading_cpp.html> (this one is exceptional in that it contains no demangling code for symbol lookup and doesn't need any non-portable libraries). > This all assumes that libc++ can cooperate with, rather than try to > replace, libc in the first place. That would depend a lot on what > platform you are on --- I think it might work OK with modern glibc, > but my last experience with C++ was back when it wasn't so. The most annoying non-cooperation for me was the STL's ignorance of Pg's MemoryContexts. I managed to tame it with a wrapper around palloc with an STL allocator interface: --8<---------------cut here---------------start------------->8--- // $Id: pg_alloc.hh,v 1.2 2005/10/19 09:59:13 andreas Exp $ // // This implements an allocator template with STL interface as a // wrapper around PostgreSQL's MemoryContexts. // // It enables STL containers to use appropriate MemoryContexts instead // of C++'s "free store". #include <stdexcept> extern "C" { #include <postgres.h> } template <class T, MemoryContext *M = &CurrentMemoryContext> class pg_allocator { public: typedef T value_type; typedef size_t size_type; typedef ptrdiff_t difference_type; typedef T* pointer; typedef const T* const_pointer; typedef T& reference; typedef const T& const_reference; pointer address(reference r) { return &r; } const_pointer address(const_reference r) { return &r; } pg_allocator() throw() { }; template <class U> pg_allocator(const pg_allocator<U, M>&) throw() { }; ~pg_allocator() throw() { }; pointer allocate(size_type n, const T *hint = 0) throw(std::bad_alloc); void deallocate(pointer p, size_type n); void construct(pointer p, const T& val) { new(p) T(val); } void destroy(pointer p) { p->~T(); } size_type max_size() const throw(); template <class U> struct rebind {typedef pg_allocator<U, M> other; }; }; template <class T, MemoryContext *M> T* pg_allocator<T, M>::allocate(size_type n, const T * hint) throw(std::bad_alloc) { void* ptr = 0; ptr = MemoryContextAlloc(*M, (n * sizeof(T))); if (ptr) return static_cast<T*>(ptr); throw std::bad_alloc(); } template <class T, MemoryContext *M> void pg_allocator<T, M>::deallocate(T* ptr, size_t n) { pfree(static_cast<void *>(ptr)); } template <class T, MemoryContext *M> bool operator==(const pg_allocator<T, M>& a, const pg_allocator<T, M>& b) { return true; } template <class T, MemoryContext *M> bool operator!=(const pg_allocator<T, M>& a, const pg_allocator<T, M>& b) { return false; } --8<---------------cut here---------------end--------------->8--- E.g., to allocate a list of strings on the CurrentMemoryContext: list<string, pg_allocator<string>> foo; You can supply a custom context with the second template argument if you need, e.g., a session-wide cache of something. At this level, I find C++ quite usable as a compromise between C and the comparatively slow procedural languages. Of course, the interface to PostgreSQL is still all PODs (plain old datatypes), but C++'s C compatibility should be seen as a strength here. regards, Andreas -- ---------------------------(end of broadcast)--------------------------- TIP 1: if posting/reading through Usenet, please send an appropriate subscribe-nomail command to majordomo@xxxxxxxxxxxxxx so that your message can get through to the mailing list cleanly