Re: Custom C function - is palloc broken?

From: Craig Ringer <craig(at)postnewspapers(dot)com(dot)au>
To: Nathan Thatcher <n8thatcher(at)gmail(dot)com>
Cc: Magnus Hagander <magnus(at)hagander(dot)net>, Dan Heron Myers <heron(at)xnapid(dot)com>, pgsql-general(at)postgresql(dot)org
Subject: Re: Custom C function - is palloc broken?
Date: 2008-05-05 07:54:13
Message-ID: 481EBD25.4000707@postnewspapers.com.au
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-general

Nathan Thatcher wrote:
> So what options does that leave all of us who need to compile and run
> our custom C functions in Windows?

After a bit of sleep and with the advantage of a now-working brain I've
got it working, at least with 8.3 .

The problem was with DLL linkage, especially the CurrentMemoryContext
global variable. I was defining BUILDING_DLL and using the PGDLLIMPORT
macro to export the copytext() function - but this was of course causing
everything in the Pg headers to be declared __declspec(dllexport)
instead of __declspec(dllimport) . AFAIK this is survivable for
functions, which will use a slower call thunk instead, but not for
exported variables.

As a result, MemoryContextAlloc(CurrentMemoryContext, (sz)) was being
called with a nonsensical pointer for CurrentMemoryContext and crashing.

To build the C function DLL correctly it correctly do not define the
BUILDING_DLL macro. Instead, define your own DLL export macros like:

#if defined(_MSC_VER) || defined(__MINGW32__)
#define COPYTEXT_EXPORT __declspec (dllexport)
#else
#define COPYTEXT_EXPORT
#endif

then declare your function as:

COPYTEXT_EXPORT Datum copytext2(PG_FUNCTION_ARGS) {
// blah blah
}

It should now be exported in the DLL's interface correctly AND have
correct access to Pg's exported functions and variables.

I did notice that I'm getting some warnings about inconsistent DLL
linkage for Pg_magic_func and pg_finfo_copytext . These really need to
be using __declspec(dllexport) rather than using __declspec(dllimport)
via PGDLLIMPORT .

Maybe it's worth providing a PGMODULEEXPORT macro for PG_MODULE_MAGIC,
PG_FUNCTION_INFO_V1, and for module writers to use to export their
functions in the DLL interface. A module author would have to ensure
that BUILDING_MODULE was defined.

Here's how the PG_MODULE_MAGIC and PG_FUNCTION_INFO_V1 macros would look:

/* This might want to go somewhere other than fmgr.h, like
* pg_config_os.h alongside the definition of PGDLLIMPORT
*/
#if defined(_MSC_VER) || defined(__MINGW32__)
#if defined(BUILDING_MODULE)
#define PGMODULEEXPORT __declspec (dllexport)
#else
// Never actually used
#define PGMODULEEXPORT __declspec (dllimport)
#endif
#else
#define PGMODULEEXPORT
#endif

#define PG_MODULE_MAGIC \
PGMODULEEXPORT Pg_magic_struct * \
PG_MAGIC_FUNCTION_NAME(void) \
{ \
static const Pg_magic_struct Pg_magic_data = PG_MODULE_MAGIC_DATA; \
return &Pg_magic_data; \
} \
extern int no_such_variable

#define PG_FUNCTION_INFO_V1(funcname) \
PGMODULEEXPORT const Pg_finfo_record * \
CppConcat(pg_finfo_,funcname) (void) \
{ \
static const Pg_finfo_record my_finfo = { 1 }; \
return &my_finfo; \
} \
extern int no_such_variable

I've tested this definition and it produces a DLL that links correctly
and does so without the warnings of inconsistent DLL linkage produced by
the original versions (which declared the function __declspec(dllimport)
then defined it).

Anyway, the C function examples need some changes to work correctly on
win32. I've attached updated versions. These redefine the
PG_MODULE_MAGIC and PG_FUNCTION_INFO_V1 macros, but if you omit that
code the module will still built, just with warnings, and will still work.

--
Craig Ringer

Attachment Content-Type Size
examples.c text/plain 4.1 KB

In response to

Responses

Browse pgsql-general by date

  From Date Subject
Next Message Javier Olazaguirre 2008-05-05 07:56:21 Re: Speed up repetitive queries
Previous Message js 2008-05-05 07:43:46 Request for Materialized Views