Re: Srf function : missing library on PostgreSQL 8.3.6 on Windows?

From: Ben Ali Rachid <souliman239(at)yahoo(dot)fr>
To: craig(at)postnewspapers(dot)com(dot)au, tgl(at)sss(dot)pgh(dot)pa(dot)us
Cc: pgsql-general(at)postgresql(dot)org
Subject: Re: Srf function : missing library on PostgreSQL 8.3.6 on Windows?
Date: 2009-03-22 16:27:58
Message-ID: 162261.89331.qm@web28504.mail.ukl.yahoo.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-general

Craig Ringer wrote :
> If you're using C++ you must also:
> - Ensure that no exceptions propagate outside your code
> - Declare all hook functions that might be dlopen()ed as extern "C"

Thanks for your advices but I'm not sure to have understood. For example, when I try to implement the "normal_rand" function from "/contrib/tablefunc" like below, I have a server crash.

/******************
 *     test.h       *
 ******************/
extern "C" {
  #include "postgres.h"
  #include "fmgr.h"
  #include "funcapi.h"
  #include "executor/spi.h"
  #include "lib/stringinfo.h"
  #include "miscadmin.h"
  #include "utils/builtins.h"
  #include "utils/guc.h"
  #include "utils/lsyscache.h"
  #include <math.h>
}
extern "C" __declspec (dllexport) Datum normal_rand(PG_FUNCTION_ARGS);

/*********************

 *      test.cpp      *

 *********************/
#include "test.h"
PG_MODULE_MAGIC;

PG_FUNCTION_INFO_V1(normal_rand);
Datum normal_rand(PG_FUNCTION_ARGS)
{
    FuncCallContext *funcctx;
    int            call_cntr;
    int            max_calls;
    normal_rand_fctx *fctx;
    float8        mean;
    float8        stddev;
    float8        carry_val;
    bool        use_carry;
    MemoryContext oldcontext;

    /* stuff done only on the first call of the function */
    if (SRF_IS_FIRSTCALL())
    {
        /* create a function context for cross-call persistence */
        funcctx = SRF_FIRSTCALL_INIT();

        /* switch to memory context appropriate for multiple function calls */
        oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);

        /* total number of tuples to be returned */
        funcctx->max_calls = PG_GETARG_UINT32(0);

        /* allocate memory for user context */
        fctx = (normal_rand_fctx *) palloc(sizeof(normal_rand_fctx));

        /*
         * Use fctx to keep track of upper and lower bounds from call to call.
         * It will also be used to carry over the spare value we get from the
         * Box-Muller algorithm so that we only actually calculate a new value
         * every other call.
         */
        fctx->mean = PG_GETARG_FLOAT8(1);
        fctx->stddev = PG_GETARG_FLOAT8(2);
        fctx->carry_val = 0;
        fctx->use_carry = false;

        funcctx->user_fctx = fctx;
        MemoryContextSwitchTo(oldcontext);
    }

    /* stuff done on every call of the function */
    funcctx = SRF_PERCALL_SETUP();

    call_cntr = funcctx->call_cntr;
    max_calls = funcctx->max_calls;
    fctx = (normal_rand_fctx*) funcctx->user_fctx;
    mean = fctx->mean;
    stddev = fctx->stddev;
    carry_val = fctx->carry_val;
    use_carry = fctx->use_carry;

    if (call_cntr < max_calls)    /* do when there is more left to send */
    {
        float8        result;
        if (use_carry)
        {
            /* reset use_carry and use second value obtained on last pass */
            fctx->use_carry = false;
            result = carry_val;
        }
        else
        {
            float8        normval_1;
            float8        normval_2;

            /* Get the next two normal values */
            get_normal_pair(&normval_1, &normval_2);

            /* use the first */
            result = mean + (stddev * normval_1);

            /* and save the second */
            fctx->carry_val = mean + (stddev * normval_2);
            fctx->use_carry = true;
        }

        /* send the result */
        SRF_RETURN_NEXT(funcctx, Float8GetDatum(result));
    }
    else
        /* do when there is no more left */
        SRF_RETURN_DONE(funcctx);
}

/*****************

 *    script        *

 *****************/

CREATE OR REPLACE FUNCTION normal_rand(int4, float8, float8)

RETURNS setof float8

AS '$libdir/tablefunc','normal_rand'

LANGUAGE C VOLATILE STRICT;

In the log file, it indicated that the server stop with an exception (0xC0000005). In the "ntstatus.h", it indicated that this exception 0xC0000005 means ACCESS VIOLATION. I don't know what causes this exception. It's also a problem with some missing " extern 'C' " ? Or is it a null pointer problem  ?

Tom Lane wrote :
> On the whole I'd recommend using plain C for backend functions if you possibly can.

Unfortunately, I must use cpp because I must translate an temporal extension  (wrote on cpp with templates, ...) from Oracle to PostgreSQL.

--

Ben Ali Rachid

Responses

Browse pgsql-general by date

  From Date Subject
Next Message Tom Lane 2009-03-22 16:57:05 Re: Srf function : missing library on PostgreSQL 8.3.6 on Windows?
Previous Message zach cruise 2009-03-22 16:27:51 Re: (odbc) multiple step ole db generated error - date/timestamp column