什么是链接Postgres服务器端C函数的适当库 [英] What is the appropriate library for linking Postgres server-side C functions

查看:99
本文介绍了什么是链接Postgres服务器端C函数的适当库的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正尝试在Ubuntu 14.04平台上为Postgres 9.5编译一些C扩展。

I am trying to compile some C extensions, on platform with Ubuntu 14.04, for Postgres 9.5.

对于我来说,我想编写C代码并进行编译它首先是一个独立的可执行文件(如下面我的Makefile所示)。这是因为我还使用NumPy API并编写了将Postgres ArrayType 数组转换为NumPy PyArray 对象的函数,并且然后使用一些NumPy数组函数。正确了解细节,正确分配 NpyIter 对象等非常棘手,因此,我肯定需要编译,运行,观察错误并测试所有 before 最终确定库构建方式的详细信息,这是我在Postgres中说创建扩展的最后一部分。

In my case, I want to write my C code and compile it first to a standalone executable (as you can see from my Makefile below). This is because I am also using the NumPy API and writing functions that convert Postgres ArrayType arrays into NumPy PyArray objects, and then use some NumPy array functions. It's very tricky to get the details right, deallocate NpyIter objects correctly, etc., so I definitely need to compile, run, observe errors, and test all before finalizing the details of how the library is built for the final part where I say CREATE EXTENSION in Postgres.

在编译时,出现几个未定义引用问题,例如:

When compiling, I get several undefined reference issues, such as:

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'

这些是Postgres C API的服务器端函数,但是具有很多Googling和很多 pgxs 强大的功能ot找出了如何获取我无法链接的后端Postgres库的名称或路径。

These are server-side functions from the Postgres C API, but with lots of Googling and lots of strongarming of pgxs I cannot figure out how to obtain the name or path of the backend Postgres library that I'm failing to link.

几乎所有搜索都只提到 libpq ,但这些功能未在该客户端API库中定义,因此我正在寻找其他内容。

Almost all searches just mention libpq, but these functions are not defined in that client-side API library, so I'm looking for something else.

作为参考,这里是我当前正在使用的Makefile。在 pg_config --libdir 中包含库目录也必须是错误的,因为它不会导致未定义的引用错误发生任何变化。

For reference, here's the Makefile I'm currently using. Including the library directory from pg_config --libdir must also be incorrect, as it does not cause any changes in the undefined reference errors.

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)

pg_config --libdir 的输出是:

user@computer:~/programming$ pg_config --libdir
/usr/lib/x86_64-linux-gnu

在该库目录中,我还找到了 libpgcommon 和当我将其添加到Makefile中时,一些未定义的引用会消失,但不是全部。这些仍然保留:

In that library directory I also found libpgcommon and when I add it to the Makefile, some of the undefined references disappear, but not all. These still remain:

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'

因此通过与 libpgcommon 链接发现了 pfree

So pfree was found by linking with libpgcommon, but nothing else.

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

Digging even further, inside of postgres.h I can see where the DatumGetFloat8 macro is defined (line 662):

#ifdef USE_FLOAT8_BYVAL
extern float8 DatumGetFloat8(Datum X);
#else
#define DatumGetFloat8(X) (* ((float8 *) DatumGetPointer(X)))
#endif

因此,必须使用 USE_FLOAT8_BYVAL 标志以某种方式安装Postgres。那是标准吗?

So, it must be the case that Postgres was installed in some way that made use of the USE_FLOAT8_BYVAL flag. Is that standard? Would you expect that from a plain Postgres install using package repos for a popular OS like Ubuntu?

鉴于此,<$ c的其他源代码或库是什么? $ c> DatumGetFloat8 是 extern 的来源吗?例如,在Google上搜索 postgres DatumGetFloat8,几乎没有发现这一点。我能找到的最好的方法是 2011年以来的消息线程说明(不确定是否正确):

Given this, what is the other source code or library from which DatumGetFloat8 is extern'd from? For example, searching Google for "postgres DatumGetFloat8" sheds pretty much no light on this. The best I can find is a message thread from 2011 stating (not sure if correctly):


缺少对DatumGetFloat8的引用意味着服务器已构建

带有float8传递值,而pljava是使用float8传递by
引用构建的。

A missing reference to DatumGetFloat8 implies that the server was built
with float8 pass by value and pljava was built with float8 pass by
reference.

pljava 位与我无关)。

推荐答案

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

A PostgreSQL extension is a shared library and not a standalone executable, so you got to use -shared -fpic -o tmp.so in your Makefile. Don't link with -lpq or -lpgcommon.

然后 gcc 不会抱怨未定义的引用–将共享库加载到PostgreSQL中时,将使用可执行文件 postgres 解决这些问题,可使用SQL命令 LOAD

Then gcc won't complain about undefined references – these will be resolved with the executable postgres when the shared library is loaded into PostgreSQL, either with the SQL command LOAD or when a PostgreSQL C function defined with that library is called.

当然,您必须使用相同的 -D 在构建PostgreSQL时定义为PostgreSQL服务器,因此例如在两个服务器中都设置或未设置 USE_FLOAT8_BYVAL 。否则您的扩展程序可能无法加载或以有趣的方式崩溃。

(因为您一直在问:按值传递 float8 并没有什么坏处;如果$ DatumGetFloat8 定义并导出到 postgres ,如果 USE_FLOAT8_BYVAL 已定义。)

Of course you'll have to use the same -D defines as the PostgreSQL server when it was built, so that for example USE_FLOAT8_BYVAL is set or unset in both. Otherwise your extension may fail to load or could crash in interesting ways.
(Since you were asking: there is nothing bad about passing float8 by value; it is actually more efficient that way if your architecture supports it. DatumGetFloat8 is defined and exported in postgres if USE_FLOAT8_BYVAL is defined.)

为了使所有操作变得容易,最好使用PostgreSQL扩展构建基础设施 PGXS

To make all that easy, it is best to use the PostgreSQL extension building infrastructure PGXS. That will take care of all these problems for you.

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

All you have to do is create an appropriate Makefile, in your case it might be as simple as

MODULES = tmp

PG_CONFIG = pg_config
PGXS := $(shell $(PG_CONFIG) --pgxs)
include $(PGXS)

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

Then run make and make install, and you are ready to go!

由于您的问题是测试和调试使用NumPy API的代码,因此您应该对PostgreSQL扩展进行模块化,以便更轻松地实现。例如,您可以编写 numpy.c ,其中包含访问该API的所有代码,以及 pgxs.c ,其中包含访问该API的所有代码。 PostgreSQL扩展代码和 numpy.c 中的函数。

然后,您可以编写特殊的测试代码并将其与 numpy链接。 o 测试您的NumPy函数。

Since your problem is to test and debug your code that uses the NumPy API, you should modularize your PostgreSQL extension so that you can do that more easily. You could for example write numpy.c which contains all the code that accesses that API and pgxs.c which contains the PostgreSQL extension code and calls functions in numpy.c.
Then you can write special testing code and link it with numpy.o to test your NumPy functions.

这篇关于什么是链接Postgres服务器端C函数的适当库的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆