【问题标题】:Creating PostgreSQL C extensions on Windows platform在 Windows 平台上创建 PostgreSQL C 扩展
【发布时间】:2014-04-14 12:12:44
【问题描述】:

我在获取一些简单的 postgres 测试函数以在 Windows 上链接和/或运行时遇到问题,我在命令行和 Visual Studio 中都进行了尝试。我找到的文档很少,也没有工作模板。

我不习惯 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.

在 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 路径并尝试将 \lib 中所有可能的 .lib 依赖项添加到命令行。我也尝试了不同的调用约定。

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

我猜这可能与 cl 包含的不匹配的系统默认值(32/64 位?)有关,但由于源仅包含来自 postgres 项目的标头,因此我希望自动解决我不知道该怎么做。

【问题讨论】:

    标签: c windows postgresql


    【解决方案1】:

    我写了一篇关于这个主题的博客,可能有用;见Compiling PostgreSQL extensions on Windows with Visual Studio

    您提到的标题问题在 9.4 系列中已修复。我会看看如何为后面的分支重新打补丁。

    而不是破解c.h,您应该只在命令行上指定定义:

    /DWIN32
    

    你也应该ensure the code is compiled as plain C:

    /Tc
    

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

    【讨论】:

    • 感谢您的信息和链接!我认为还应该使用在 Windows 上编译示例的步骤来更新文档(尽管可能不一定是更复杂的 IDE 方式),因为它很容易做到,但你自己却有点难以弄清楚。 :) 就目前而言,仅涵盖 *nix 并且没有提到您需要 PGDLLEXPORT。 (当然我可以自己提供建议文本,但如果是这样的话,只有在获得更多经验之后才能这样做..)
    • MVS 社区版工作正常吗,我们可以使用 ut 编译例如 pglogical 扩展?!
    【解决方案2】:

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

    我只是使用了错误版本的命令提示符,所以当使用 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' type redefinition (postgres),在接受的答案中,链接到带有附加差异的邮件列表)

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

    【讨论】:

      猜你喜欢
      • 2019-05-16
      • 2012-03-11
      • 2012-03-26
      • 2013-08-08
      • 2016-01-04
      • 2020-06-25
      • 1970-01-01
      • 1970-01-01
      • 2017-09-26
      相关资源
      最近更新 更多