Re: server-side extension in c++ - Mailing list pgsql-general

From Bruce Momjian
Subject Re: server-side extension in c++
Date
Msg-id 201006020326.o523QXM01845@momjian.us
Whole thread Raw
In response to Re: server-side extension in c++  (Craig Ringer <craig@postnewspapers.com.au>)
List pgsql-general
Craig Ringer wrote:
> ( 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:

This was very helpful.  I have condensed your ideas into the attached
patch that contains the potential C++ documentation section.

--
  Bruce Momjian  <bruce@momjian.us>        http://momjian.us
  EnterpriseDB                             http://enterprisedb.com

  + None of us is going to be here forever. +
Index: doc/src/sgml/extend.sgml
===================================================================
RCS file: /cvsroot/pgsql/doc/src/sgml/extend.sgml,v
retrieving revision 1.42
diff -c -c -r1.42 extend.sgml
*** doc/src/sgml/extend.sgml    1 Jun 2010 03:19:36 -0000    1.42
--- doc/src/sgml/extend.sgml    2 Jun 2010 03:25:30 -0000
***************
*** 273,280 ****
    &xoper;
    &xindex;

- <!-- Use this someday when C++ is easier to use. bjm 2010-05-31
-
    <sect1 id="extend-Cpp">
     <title>Using C++ for Extensibility</title>

--- 273,278 ----
***************
*** 284,325 ****

     <para>
      It is possible to use a compiler in C++ mode to build
!     <productname>PostgreSQL</productname> extensions;  you must simply
!     follow the standard methods for dynamically linking to C executables:

      <itemizedlist>
       <listitem>
        <para>
!         Use <literal>extern C</> linkage for all functions that must
!         be accessible by <function>dlopen()</>.  This is also necessary
!         for any functions that might be passed as pointers between
!         the backend and C++ code.
        </para>
       </listitem>
       <listitem>
        <para>
!        Use <function>palloc()</> to allocate any memory that might be
!        freed by the backend C code (don't pass <function>new()</>-allocated
!        memory).
!       </para>
       </listitem>
       <listitem>
        <para>
!        Use <function>pfree()</> to free memory allocated by the backend
!        C code (do not use <function>delete()</> for such cases).
        </para>
       </listitem>
       <listitem>
        <para>
!        Prevent exceptions from propagating into the C code (use a
!        catch-all block at the top level of all <literal>extern C</>
!        functions).
        </para>
       </listitem>
      </itemizedlist>
     </para>

    </sect1>
- -->

   </chapter>
--- 282,338 ----

     <para>
      It is possible to use a compiler in C++ mode to build
!     <productname>PostgreSQL</productname> extensions by following these
!     guidelines:

      <itemizedlist>
       <listitem>
        <para>
!         All functions accessed by the backend must present a C interface
!         to the backend;  these C functions can then call C++ functions.
!         For example, <literal>extern C</> linkage is required for
!         backend-accessed functions.  This is also necessary for any
!         functions that are passed as pointers between the backend and
!         C++ code.
        </para>
       </listitem>
       <listitem>
        <para>
!        Free memory using the appropriate deallocation method.  For example,
!        most backend memory is allocated using <function>palloc()</>, so use
!        <function>pfree()</> to free it, i.e. using C++
!        <function>delete()</> in such cases will fail.
       </listitem>
       <listitem>
        <para>
!        Prevent exceptions from propagating into the C code (use a
!        catch-all block at the top level of all <literal>extern C</>
!        functions).  This is necessary even if the C++ code does not
!        throw any exceptions because events like out-of-memory still
!        throw exceptions.  Any exceptions must be caught and appropriate
!        errors passed back to the C interface.  If possible, compile C++
!        with <option>-fno-exceptions</> to eliminate exceptions entirely;
!        in such cases, you must check for failures in your C++ code, e.g.
!        check for NULL returned by <function>new()</>.
        </para>
       </listitem>
       <listitem>
        <para>
!        If calling backend functions from C++ code, be sure that the
!        C++ call stack contains only plain old data structure
!        (<acronym>POD</>).  This is necessary because backend errors
!        generate a <function>longjump()</> that does not properly unroll
!        a C++ call stack with non-POD objects.
        </para>
       </listitem>
      </itemizedlist>
     </para>

+    <para>
+     In summary, it is best to place C++ code behind a wall of
+     <literal>extern C</> functions that interface to the backend,
+     and avoid exception, memory, and call stack leakage.
+    </para>
    </sect1>

   </chapter>

pgsql-general by date:

Previous
From: Tom Lane
Date:
Subject: Re: Disable executing external commands from psql?
Next
From: Ken Tanzer
Date:
Subject: Re: Disable executing external commands from psql?