From c8ead2a3974d3eada145a0e18940150039493cc9 Mon Sep 17 00:00:00 2001
From: Tom Lane <tgl@sss.pgh.pa.us>
Date: Fri, 4 Nov 2016 19:04:56 -0400
Subject: [PATCH] Provide DLLEXPORT markers for C functions via
 PG_FUNCTION_INFO_V1 macro.

Second try at the change originally made in commit 8518583cd;
this time with contrib updates so that manual extern declarations
are also marked with PGDLLEXPORT.  The release notes should point
this out as a significant source-code change for extension authors,
since they'll have to make similar additions to avoid trouble on Windows.

Laurenz Albe, doc change by me

Patch: <A737B7A37273E048B164557ADEF4A58B53962ED8@ntex2010a.host.magwien.gv.at>
---
 contrib/hstore/hstore.h |  2 +-
 contrib/ltree/ltree.h   | 40 ++++++++++++++++++++--------------------
 doc/src/sgml/xfunc.sgml | 17 +++++++++++++++++
 src/include/fmgr.h      |  7 +++----
 4 files changed, 41 insertions(+), 25 deletions(-)

diff --git a/contrib/hstore/hstore.h b/contrib/hstore/hstore.h
index 6bab08b7de0..6303fa40619 100644
--- a/contrib/hstore/hstore.h
+++ b/contrib/hstore/hstore.h
@@ -194,7 +194,7 @@ extern Pairs *hstoreArrayToPairs(ArrayType *a, int *npairs);
 #if HSTORE_POLLUTE_NAMESPACE
 #define HSTORE_POLLUTE(newname_,oldname_) \
 	PG_FUNCTION_INFO_V1(oldname_);		  \
-	Datum newname_(PG_FUNCTION_ARGS);	  \
+	extern PGDLLEXPORT Datum newname_(PG_FUNCTION_ARGS); \
 	Datum oldname_(PG_FUNCTION_ARGS) { return newname_(fcinfo); } \
 	extern int no_such_variable
 #else
diff --git a/contrib/ltree/ltree.h b/contrib/ltree/ltree.h
index c604357dbfb..c7aa7f88188 100644
--- a/contrib/ltree/ltree.h
+++ b/contrib/ltree/ltree.h
@@ -130,30 +130,30 @@ typedef struct
 
 
 /* use in array iterator */
-Datum		ltree_isparent(PG_FUNCTION_ARGS);
-Datum		ltree_risparent(PG_FUNCTION_ARGS);
-Datum		ltq_regex(PG_FUNCTION_ARGS);
-Datum		ltq_rregex(PG_FUNCTION_ARGS);
-Datum		lt_q_regex(PG_FUNCTION_ARGS);
-Datum		lt_q_rregex(PG_FUNCTION_ARGS);
-Datum		ltxtq_exec(PG_FUNCTION_ARGS);
-Datum		ltxtq_rexec(PG_FUNCTION_ARGS);
-Datum		_ltq_regex(PG_FUNCTION_ARGS);
-Datum		_ltq_rregex(PG_FUNCTION_ARGS);
-Datum		_lt_q_regex(PG_FUNCTION_ARGS);
-Datum		_lt_q_rregex(PG_FUNCTION_ARGS);
-Datum		_ltxtq_exec(PG_FUNCTION_ARGS);
-Datum		_ltxtq_rexec(PG_FUNCTION_ARGS);
-Datum		_ltree_isparent(PG_FUNCTION_ARGS);
-Datum		_ltree_risparent(PG_FUNCTION_ARGS);
+extern PGDLLEXPORT Datum ltree_isparent(PG_FUNCTION_ARGS);
+extern PGDLLEXPORT Datum ltree_risparent(PG_FUNCTION_ARGS);
+extern PGDLLEXPORT Datum ltq_regex(PG_FUNCTION_ARGS);
+extern PGDLLEXPORT Datum ltq_rregex(PG_FUNCTION_ARGS);
+extern PGDLLEXPORT Datum lt_q_regex(PG_FUNCTION_ARGS);
+extern PGDLLEXPORT Datum lt_q_rregex(PG_FUNCTION_ARGS);
+extern PGDLLEXPORT Datum ltxtq_exec(PG_FUNCTION_ARGS);
+extern PGDLLEXPORT Datum ltxtq_rexec(PG_FUNCTION_ARGS);
+extern PGDLLEXPORT Datum _ltq_regex(PG_FUNCTION_ARGS);
+extern PGDLLEXPORT Datum _ltq_rregex(PG_FUNCTION_ARGS);
+extern PGDLLEXPORT Datum _lt_q_regex(PG_FUNCTION_ARGS);
+extern PGDLLEXPORT Datum _lt_q_rregex(PG_FUNCTION_ARGS);
+extern PGDLLEXPORT Datum _ltxtq_exec(PG_FUNCTION_ARGS);
+extern PGDLLEXPORT Datum _ltxtq_rexec(PG_FUNCTION_ARGS);
+extern PGDLLEXPORT Datum _ltree_isparent(PG_FUNCTION_ARGS);
+extern PGDLLEXPORT Datum _ltree_risparent(PG_FUNCTION_ARGS);
 
 /* Concatenation functions */
-Datum		ltree_addltree(PG_FUNCTION_ARGS);
-Datum		ltree_addtext(PG_FUNCTION_ARGS);
-Datum		ltree_textadd(PG_FUNCTION_ARGS);
+extern PGDLLEXPORT Datum ltree_addltree(PG_FUNCTION_ARGS);
+extern PGDLLEXPORT Datum ltree_addtext(PG_FUNCTION_ARGS);
+extern PGDLLEXPORT Datum ltree_textadd(PG_FUNCTION_ARGS);
 
 /* Util function */
-Datum		ltree_in(PG_FUNCTION_ARGS);
+extern PGDLLEXPORT Datum ltree_in(PG_FUNCTION_ARGS);
 
 bool ltree_execute(ITEM *curitem, void *checkval,
 			  bool calcnot, bool (*chkcond) (void *checkval, ITEM *val));
diff --git a/doc/src/sgml/xfunc.sgml b/doc/src/sgml/xfunc.sgml
index de6a466efc5..6060e618576 100644
--- a/doc/src/sgml/xfunc.sgml
+++ b/doc/src/sgml/xfunc.sgml
@@ -2577,6 +2577,23 @@ concat_text(PG_FUNCTION_ARGS)
         error messages to this effect.
        </para>
       </listitem>
+
+      <listitem>
+       <para>
+        To work correctly on Windows, <literal>C</>-language functions need
+        to be marked with <literal>PGDLLEXPORT</>, unless you use a build
+        process that marks all global functions that way.  In simple cases
+        this detail will be handled transparently by
+        the <literal>PG_FUNCTION_INFO_V1</> macro.  However, if you write
+        explicit external declarations (perhaps in header files), be sure
+        to write them like this:
+<programlisting>
+extern PGDLLEXPORT Datum funcname(PG_FUNCTION_ARGS);
+</programlisting>
+        or you'll get compiler complaints when building on Windows.  (On
+        other platforms, the <literal>PGDLLEXPORT</> macro does nothing.)
+       </para>
+      </listitem>
      </itemizedlist>
     </para>
    </sect2>
diff --git a/src/include/fmgr.h b/src/include/fmgr.h
index 0878418516e..3668ac3f6e9 100644
--- a/src/include/fmgr.h
+++ b/src/include/fmgr.h
@@ -350,12 +350,11 @@ typedef const Pg_finfo_record *(*PGFInfoFunction) (void);
  *
  *	On Windows, the function and info function must be exported.  Our normal
  *	build processes take care of that via .DEF files or --export-all-symbols.
- *	Module authors using a different build process might need to manually
- *	declare the function PGDLLEXPORT.  We do that automatically here for the
- *	info function, since authors shouldn't need to be explicitly aware of it.
+ *	Module authors using a different build process might do it differently,
+ *	so we declare these functions PGDLLEXPORT for their convenience.
  */
 #define PG_FUNCTION_INFO_V1(funcname) \
-extern Datum funcname(PG_FUNCTION_ARGS); \
+extern PGDLLEXPORT Datum funcname(PG_FUNCTION_ARGS); \
 extern PGDLLEXPORT const Pg_finfo_record * CppConcat(pg_finfo_,funcname)(void); \
 const Pg_finfo_record * \
 CppConcat(pg_finfo_,funcname) (void) \
-- 
GitLab