在Windows平台上创建PostgreSQL C扩展

在Windows平台上创建PostgreSQL C扩展,c,windows,postgresql,C,Windows,Postgresql,我在命令行和VisualStudio中都尝试过,但在获取一些简单的测试函数以供postgres在Windows上链接和/或运行时遇到问题。我发现很少有文档,也没有用于此的工作模板 我不习惯Windows中的编译工具,而且我是postgres的新手,所以我可能缺少一些非常基本的东西。任何指示将不胜感激 使用:Windows 8.0(64位)、cl.exe 18.00.21005.1、link.exe 12.00.21005.1、PostgreSQL v.9.3.4(二进制安装) 这是文档中的示例代

我在命令行和VisualStudio中都尝试过,但在获取一些简单的测试函数以供postgres在Windows上链接和/或运行时遇到问题。我发现很少有文档,也没有用于此的工作模板

我不习惯Windows中的编译工具,而且我是postgres的新手,所以我可能缺少一些非常基本的东西。任何指示将不胜感激

使用:Windows 8.0(64位)、cl.exe 18.00.21005.1、link.exe 12.00.21005.1、PostgreSQL v.9.3.4(二进制安装)

这是文档中的示例代码,只是为了简单起见,我只添加了PGDLLEXPORT调用:

#include "postgres.h"
#include "fmgr.h"

PG_MODULE_MAGIC;
PG_FUNCTION_INFO_V1(add_one);

PGDLLEXPORT Datum
add_one(PG_FUNCTION_ARGS)
{
    int32   arg = PG_GETARG_INT32(0);

    PG_RETURN_INT32(arg + 1);
}
在我的cl命令文件中,我收集了以下包含路径:

/I "C:\Program Files\PostgreSQL\9.3\include\server\port\win32_msvc"
/I "C:\Program Files\PostgreSQL\9.3\include\server\port\win32"
/I "C:\Program Files\PostgreSQL\9.3\include\server\port"
/I "C:\Program Files\PostgreSQL\9.3\include\server"
/I "C:\Program Files\PostgreSQL\9.3\include"
然后运行:

cl /c add.c @includes
link /DLL add.obj "C:\Program Files\PostgreSQL\9.3\lib\postgres.lib"
它编译和链接时没有错误或警告。我将创建的add.dll放在postgres\lib目录中,并将使用psql登录的相应函数定义为用户postgres:

CREATE FUNCTION add_one(integer) RETURNS integer
AS 'add','add_one'
LANGUAGE C STRICT;
其中我得到了以下错误:

ERROR:  could not load library "C:/Program Files/PostgreSQL/9.3/lib/add.dll": %1 is not a valid Win32 application.
在VisualStudio中构建dll时,结果是相同的

我最初打算编写的扩展更为复杂,还包括用于使用复合参数和返回的“funcapi.h”。在这种情况下,它的编译也没有问题,但在链接阶段失败,出现以下类型的错误:

error LNK2019: unresolved external symbol _get_call_result_type ...
error LNK2019: unresolved external symbol _BlessTupleDesc ...
error LNK2019: unresolved external symbol _heap_form_tuple ...
无论是使用命令行还是MSVC,检查lib路径并尝试将\lib中所有可能的.lib依赖项添加到命令行,都是一样的。我还尝试了不同的通话约定

但是,无论如何,我需要先让简单的DLL导出工作起来,也许解决方案与同一问题有关

我猜这可能与cl包含的系统默认值不匹配(32/64位?)有关,但由于源代码只包含postgres项目的标题,我希望这会自动解决,我不知道如何继续

实际上这是可行的(命令行方法)

我只是使用了错误版本的命令提示符,因此,当使用VS2012 x64 Cross Tools命令提示符执行与上述相同的过程时,我可以使用postgres文档中的所有示例函数

编辑:如果您得到编译错误C2011:“时区”:“结构”类型重新定义,我将在下面对此进行评论,请参阅Craig Ringers Response以获得更好的处理方法

如果其他人对此感到困惑,我还可以告诉他们我必须修改一个头文件,include\c.h,添加以下内容:

#if defined(_WIN32)
#define WIN32
#endif
在代码中此部分之前:

#if !defined(WIN32) && !defined(__CYGWIN__)     /* win32 includes further down */
#include "pg_config_os.h"       /* must be before any system header files */
#endif
如果没有它,就会出现编译错误

(我是从这条线得到的: ,在已接受的答案中,链接到带有附加差异的邮件列表)


我不知道这是否是在Windows中构建扩展的最佳方式,但至少你不需要编译整个源代码树就可以开始学习了。

我写了一篇关于这个主题的博客,可能会很有用;看

您提到的标题问题在9.4系列中已修复。我会考虑为后面的分支打回补丁

您应该在命令行中指定define,而不是hacking
c.h

/DWIN32
你亦应:


当然,您必须在正确的VisualStudio命令提示符环境下运行,x86或x64编译器取决于所需的目标。如果您不确定,可以在不带参数的情况下运行
cl.exe
进行检查;它将打印目标体系结构。

感谢您提供的信息和链接!我认为文档也应该更新为在Windows上编译示例的步骤(虽然可能不一定是更复杂的IDE方式),因为这很容易做到,但自己却有点难以理解。:)就目前情况而言,仅包含*nix,未提及您将需要PGDLLEXPORT。(当然,我可以自己提供一个建议文本,但如果是这样的话,只有在获得更多的经验之后……)MVS社区版工作正常吗,我们可以使用ut来编译例如pglogical extension?!
/Tc