什么是用于链接Postgres服务器端C函数的适当库

ely*_*ely 7 c postgresql

我正在尝试使用Ubuntu 14.04在Postgres 9.5的平台上编译一些C扩展.

在我的例子中,我想编写我的C代码并首先将其编译为独立的可执行文件(如下面的Makefile中所示).这是因为我还使用NumPy API并编写将Postgres ArrayType数组转换为NumPy PyArray对象的函数,然后使用一些NumPy数组函数.获取正确的细节,正确释放NpyIter对象等等是非常棘手的,所以我绝对需要编译,运行,观察错误并测试所有内容,然后在最后部分详细说明库的构建方式我CREATE EXTENSION在Postgres中说的最后部分.

在编译时,我得到了几个未定义的引用问题,例如:

tmp.c:(.text+0x2d6): undefined reference to `get_typlenbyvalalign'
tmp.c:(.text+0x346): undefined reference to `deconstruct_array'
tmp.c:(.text+0x41f): undefined reference to `DatumGetFloat8'
tmp.c:(.text+0x4ae): undefined reference to `pfree'
tmp.c:(.text+0x4ba): undefined reference to `pfree'
Run Code Online (Sandbox Code Playgroud)

这些是来自Postgres C API的服务器端函数,但是有很多谷歌搜索和大量的强大的pgxs我无法弄清楚如何获取我无法链接的后端Postgres库的名称或路径.

几乎所有的搜索都提到了libpq,但是这些函数没有在客户端API库中定义,所以我正在寻找其他东西.

作为参考,这是我目前正在使用的Makefile.包括库目录pg_config --libdir也必须是不正确的,因为它不会导致未定义的引用错误的任何更改.

INCLUDEDIRS := -I.
INCLUDEDIRS += -I/usr/include/python2.7
INCLUDEDIRS += -I/home/username/anaconda/lib/python2.7/site-packages/numpy/core/include
INCLUDEDIRS += -I$(shell pg_config --includedir-server)
INCLUDEDIRS += -I$(shell pg_config --includedir)

LIBS := -L$(shell pg_config --libdir)
LIBS += -lpython2.7

tmp: tmp.c Makefile
    gcc tmp.c -o tmp $(INCLUDEDIRS) $(LIBS)
Run Code Online (Sandbox Code Playgroud)

输出pg_config --libdir是:

user@computer:~/programming$ pg_config --libdir
/usr/lib/x86_64-linux-gnu
Run Code Online (Sandbox Code Playgroud)

在那个库目录中我也找到了libpgcommon,当我将它添加到Makefile时,一些未定义的引用会消失,但不是全部.这些仍然存在:

tmp.c:(.text+0x2d6): undefined reference to `get_typlenbyvalalign'
tmp.c:(.text+0x346): undefined reference to `deconstruct_array'
tmp.c:(.text+0x41f): undefined reference to `DatumGetFloat8'
Run Code Online (Sandbox Code Playgroud)

因此,pfree通过与联发现libpgcommon,但没有别的.

进一步挖掘,postgres.h我可以看到DatumGetFloat8宏的定义(第662行):

#ifdef USE_FLOAT8_BYVAL
extern float8 DatumGetFloat8(Datum X);
#else
#define DatumGetFloat8(X) (* ((float8 *) DatumGetPointer(X)))
#endif
Run Code Online (Sandbox Code Playgroud)

因此,必须是Postgres以某种方式安装使用USE_FLOAT8_BYVAL旗帜的情况.那是标准吗?您是否期望从普通的Postgres安装使用包Repos来安装像Ubuntu这样的流行操作系统?

鉴于此,从中获取的其他源代码或库DatumGetFloat8extern什么?例如,在Google上搜索"postgres DatumGetFloat8"几乎没有说明这一点.我能找到的最好的是来自2011年消息线程(不确定是否正确):

缺少对DatumGetFloat8的引用意味着服务器是
使用float8传递值构建的,而pljava是使用float8传递
引用构建的.

(这pljava与我无关).

Lau*_*lbe 3

PostgreSQL 扩展是一个共享库,而不是独立的可执行文件,因此您必须-shared -fpic -o tmp.so在 Makefile 中使用。不要与-lpq或链接-lpgcommon

然后gcc就不会抱怨未定义的引用——postgres当共享库加载到 PostgreSQL 中时,无论是使用 SQL 命令LOAD还是调用使用该库定义的 PostgreSQL C 函数时,这些都将通过可执行文件进行解析。

当然,您必须-D在构建 PostgreSQL 服务器时使用与它相同的定义,以便USE_FLOAT8_BYVAL在两者中设置或取消设置。否则,您的扩展可能无法加载或可能以有趣的方式崩溃。
(既然你问了:按值传递没有什么不好float8;如果你的架构支持它,这种方式实际上会更有效。在if被定义DatumGetFloat8中定义和导出。)postgresUSE_FLOAT8_BYVAL

为了使这一切变得简单,最好使用 PostgreSQL 扩展构建基础设施PGXS。这将为您解决所有这些问题。

您所要做的就是创建一个合适的Makefile,在您的情况下它可能很简单

MODULES = tmp

PG_CONFIG = pg_config
PGXS := $(shell $(PG_CONFIG) --pgxs)
include $(PGXS)
Run Code Online (Sandbox Code Playgroud)

然后运行make​​和make install,您就可以开始了!

由于您的问题是测试和调试使用 NumPy API 的代码,因此您应该模块化 PostgreSQL 扩展,以便更轻松地做到这一点。例如,您可以编写numpy.c其中包含访问该 API 的所有代码以及pgxs.c包含 PostgreSQL 扩展代码和调用numpy.c.
然后您可以编写特殊的测试代码并将其链接到numpy.o测试您的 NumPy 函数。

  • 假设我想包含一个“main”函数并首先将扩展构建为独立的可执行文件,但仍然调用服务器端 C-API Postgres 函数,首先在纯 C 中测试它,然后再将其构建为共享对象并安装它与 Postgres 一起。你可以从我的 Makefile 中看到这就是我正在尝试做的事情。如何构建独立的可执行文件? (2认同)