在Windows平台上创建PostgreSQL C扩展

3
我在Windows上尝试通过命令行和Visual Studio获取一些简单的PostgreSQL测试函数,并使其链接和/或运行存在问题。我发现很少有文档,也没有有效的模板可用。
我不熟悉Windows上的编译工具,而且我对PostgreSQL也是新手,可能会错过一些非常基本的东西。如有任何指导,将不胜感激!
使用的工具为: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目录中,并在以用户postgres身份登录的psql中定义相应的函数:

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.

在使用Visual Studio构建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依赖项添加到命令行中。我还尝试了不同的调用约定。
但无论如何,我首先需要让简单的DLL导出正常工作,也许解决方案与相同问题有关。
我猜想这可能与cl包含的系统默认值不匹配(32/64位?)有关,但由于源代码只包括来自postgres项目的头文件,我希望这会被自动解决,但我不知道该怎么处理。
2个回答

2
我写了一篇关于这个主题的博客,可能会有用;请参见使用Visual Studio在Windows上编译PostgreSQL扩展
你提到的头文件问题已在9.4系列中得到解决。我会考虑将其回溯到旧版本。
与其修改文件,你应该在命令行上指定定义。
/DWIN32

您还应该确保代码编译为纯C

/Tc

当然,你必须在正确的Visual Studio命令提示环境下运行,并根据所需目标选择x86或x64编译器。如果您不确定,可以通过运行cl.exe而不使用参数来检查它,它将打印目标架构。


谢谢提供的信息和链接!我认为文档也应该更新,加上在Windows上编译示例的步骤(尽管可能不需要更复杂的IDE方式),因为这样做非常容易,但自己弄清楚有点困难。目前只涵盖了*nix,并没有提到你需要PGDLLEXPORT。(当然,我可以自己提供建议的文本,但只有在对此有更多经验之后才能这样做。) - samson75
MVS社区版是否正常工作,我们可以使用它来编译例如pglogical扩展吗? - Charif DZ
链接已过期! - ashveli
@ashveli 感谢你指出这个问题。网站管理员团队已经修复了链接重定向的问题。 - Craig Ringer

0

实际上这个方法是有效的(命令行方法)。

我只是使用了错误版本的命令提示符,所以当我使用与上述相同的步骤在VS2012 x64交叉工具命令提示符中时,我可以使所有来自postgres文档的示例函数正常工作。

编辑:如果你遇到了我在下面评论的编译错误C2011: 'timezone':'struct' type redefinition,可以参考Craig Ringers的答案来更好地处理它。

如果其他人也遇到了这个问题,我还可以告诉你,我不得不修改一个头文件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

如果没有它,将会出现编译错误。

(我从这个主题中得到的信息: error C2011:'timezone':'struct'类型重定义(postgres), 在被接受的答案中,附带差异的邮件列表链接)

我不知道这是否是在Windows上构建扩展的最佳方式,但至少你不需要编译整个源代码树就能够开始学习和进行开发。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接