Обсуждение: Srf function : missing library on PostgreSQL 8.3.6 on Windows?

Поиск
Список
Период
Сортировка

Srf function : missing library on PostgreSQL 8.3.6 on Windows?

От
Ben Ali Rachid
Дата:
Hello,

I try to use the srf API and I have a link error. When I did :

FuncCallContext *funcctx;
...
if (SRF_IS_FIRSTCALL()){
funcctx = SRF_FIRSTCALL_INIT(); // If I remove this line, no link error
...
}

I have this link error : "undefined reference to 'init_MultiFuncCall(FunctionCallInfoData*)'". The init_MultiFuncCal function is in the funcapi.h file, but where is the associated library ? I try all the libraries of PostreSQL, but no success .

Any idea ? Thanks.

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

От
Tom Lane
Дата:
Ben Ali Rachid <souliman239@yahoo.fr> writes:
> I have this link error : "undefined reference to 'init_MultiFuncCall(FunctionCallInfoData*)'".

The fact that the linker knows the argument data type indicates that
you're trying to compile your code as C++.  Postgres is written in C,
not C++.

You can try putting extern "C" { ... } around your inclusions of
Postgres header files, but you're likely to run into other problems
later on.  On the whole I'd recommend using plain C for backend
functions if you possibly can.

            regards, tom lane

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

От
Ben Ali Rachid
Дата:

Thanks for your help. I try "extern C" for the inclusions and everything is OK. But now I have execution error (server crash), but it's another problem that I will try to solve.

--- En date de : Ven 20.3.09, Tom Lane <tgl@sss.pgh.pa.us> a écrit :

De: Tom Lane <tgl@sss.pgh.pa.us>
Objet: Re: [GENERAL] Srf function : missing library on PostgreSQL 8.3.6 on Windows?
À: "Ben Ali Rachid" <souliman239@yahoo..fr>
Cc: pgsql-general@postgresql.org
Date: Vendredi 20 Mars 2009, 16h37

Ben Ali Rachid <souliman239@yahoo.fr> writes:
> I have this link error : "undefined reference to 'init_MultiFuncCall(FunctionCallInfoData*)'".

The fact that the linker knows the argument data type indicates that
you're trying to compile your code as C++.  Postgres is written in C,
not C++.

You can try putting extern "C" { ... } around your inclusions of
Postgres header files, but you're likely to run into other problems
later on.  On the whole I'd recommend using plain C for backend
functions if you possibly can.

            regards, tom lane

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

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

От
Craig Ringer
Дата:
Ben Ali Rachid wrote:
> Thanks for your help. I try "extern C" for the inclusions and everything is OK. But now I have execution error
(servercrash), but it's another problem that I will try to solve.  

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"

As Tom Lane pointed out in an earlier thread about this you'll also have
problems with Pg's longjmp based error handling skipping past
exception-driven cleanup, so you can't rely on RAII and scoped objects.

--
Craig Ringer

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

От
Ben Ali Rachid
Дата:
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

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

От
Tom Lane
Дата:
Ben Ali Rachid <souliman239@yahoo.fr> writes:
> Craig Ringer wrote :
>> - Declare all hook functions that might be dlopen()ed as extern "C"

> Thanks for your advices but I'm not sure to have understood.

PG_FUNCTION_INFO_V1() generates a function that has to have "C" linkage.
So does PG_MODULE_MAGIC.  I'm actually not sure how you got the module
to load at all with the latter point ...

            regards, tom lane

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

От
Ben Ali Rachid
Дата:

Tom Lane wrote :
> PG_FUNCTION_INFO_V1() generates a function that has to have "C" linkage.
> So does PG_MODULE_MAGIC.  I'm actually not sure how you got the module
> to load at all with the latter point ...

Sorry, I forgot this in my previous post :

#ifdef __cplusplus
extern "C" {
#endif

--

#ifdef __cplusplus
}
#endif

I also forgot the definition of the function 'get_normal_pair'. So my (correct) cpp file is like below :

#include "dll.h"

#ifdef __cplusplus
extern "C" {
#endif

PG_MODULE_MAGIC;

void get_normal_pair(float8 *x1, float8 *x2);
void get_normal_pair(float8 *x1, float8 *x2)
{
    float8     u1,
                u2,
                v1,
                v2,
                s;
    do
    {
        u1 = (float8) rand() / (float8) MAX_RANDOM_VALUE;
        u2 = (float8) rand() / (float8) MAX_RANDOM_VALUE;
        v1 = (2.0 * u1) - 1.0;
        v2 = (2.0 * u2) - 1.0;
        s = v1 * v1 + v2 * v2;
    }
    while (s >= 1.0);

    if (s == 0)
    {
        *x1 = 0;
        *x2 = 0;
    }
    else
    {
        s = sqrt((-2.0 * log(s)) / s);
        *x1 = v1 * s;
        *x2 = v2 * s;
    }
}

typedef struct
{
    float8        mean;             /* mean of the distribution */
    float8        stddev;            /* stddev of the distribution */
    float8        carry_val;        /* hold second generated value */
    bool         use_carry;        /* use second generated value */
} normal_rand_fctx;


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);
}

#ifdef __cplusplus
}
#endif

I have no problem when I load the DLL (no 'missing magic block' error). The server crashes when I try : SELECT normal_rand(5, 10.0, 20.0) or SELECT * FROM normal_rand(5, 10.0, 20.0).

--
Ben Ali Rachid


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

От
Tom Lane
Дата:
Ben Ali Rachid <souliman239@yahoo.fr> writes:
> I have no problem when I load the DLL (no 'missing magic block' error). The server crashes when I try : SELECT
normal_rand(5,10.0, 20.0) or SELECT * FROM normal_rand(5, 10.0, 20.0). 

Well, the next step would be to get out your debugger and try to
identify exactly where it's crashing.

            regards, tom lane