PostgreSQL provides a way to load C extension modules with its internal FMGR. Unfortunately there is no portable way for an extension module to initialize (directly after the pg_dlopen() of the DSO) and to finish (directly before the pg_dlclose() of the DSO). This way it is mostly impossible to write a more complex extension module in a portable way.
The only to me known workarounds are either to call an own initialization function at the start of _EVERY_ exported function manually (works, but is ugly and especially doesn't work for the finishing function!) or to leverage some platform specific hacks like the implicitly called _init and _fini functions (is what the ODBC extension module currently does, but is horribly platform specific and not portable). Hence I propose the patch below (applies to PostgreSQL 8.1.4) which mimics the dlopen(3) and dlclose(3) behaviour of some Unix platforms and resolves and calls _PG_init and _PG_fini functions of an extension module right after/before the pg_dlopen/pg_dlclose calls in the FMGR. This is both a fully portable solution and fully backward compatible to existing and forthcoming extension modules (except they really would have _PG_init and _PG_fini functions already defined). Ralf S. Engelschall [EMAIL PROTECTED] www.engelschall.com Index: src/backend/utils/fmgr/dfmgr.c --- src/backend/utils/fmgr/dfmgr.c.orig 2005-10-15 04:49:32 +0200 +++ src/backend/utils/fmgr/dfmgr.c 2006-08-02 20:48:48 +0200 @@ -60,6 +60,10 @@ static char *expand_dynamic_library_name(const char *name); static char *substitute_libpath_macro(const char *name); +/* types for PostgreSQL-specific DSO init/fini functions */ +typedef void (*PG_init_t)(void); +typedef void (*PG_fini_t)(void); + /* * Load the specified dynamic-link library file, and look for a function * named funcname in it. (funcname can be NULL to just load the file.) @@ -82,6 +86,7 @@ char *load_error; struct stat stat_buf; char *fullname; + PG_init_t *PG_init; fullname = expand_dynamic_library_name(filename); if (!fullname) @@ -146,6 +151,13 @@ fullname, load_error))); } + /* optionally give the DSO a chance to initialize by calling a + PostgreSQL-specific (and this way portable) "_PG_init" function + similar to what dlopen(3) implicitly does with "_init" on some + Unix platforms. */ + if ((PG_init = (PG_init_t *)pg_dlsym(file_scanner->handle, "_PG_init")) != NULL) + (*PG_init)(); + /* OK to link it into list */ if (file_list == NULL) file_list = file_scanner; @@ -192,6 +204,7 @@ *nxt; struct stat stat_buf; char *fullname; + PG_fini_t *PG_fini; fullname = expand_dynamic_library_name(filename); if (!fullname) @@ -224,6 +237,14 @@ else file_list = nxt; clear_external_function_hash(file_scanner->handle); + + /* optionally give the DSO a chance to finish by calling + a PostgreSQL-specific (and this way portable) "_PG_fini" + function similar to what dlopen(3) implicitly does with + "_fini" on some Unix platforms. */ + if ((PG_fini = (PG_init_t *)pg_dlsym(file_scanner->handle, "_PG_fini")) != NULL) + (*PG_fini)(); + pg_dlclose(file_scanner->handle); free((char *) file_scanner); /* prv does not change */ ---------------------------(end of broadcast)--------------------------- TIP 5: don't forget to increase your free space map settings