我正在尝试使用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这样的流行操作系统?
鉴于此,从中获取的其他源代码或库DatumGetFloat8是extern什么?例如,在Google上搜索"postgres DatumGetFloat8"几乎没有说明这一点.我能找到的最好的是来自2011年的消息线程(不确定是否正确):
缺少对DatumGetFloat8的引用意味着服务器是
使用float8传递值构建的,而pljava是使用float8传递
引用构建的.
(这pljava与我无关).
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 函数。
| 归档时间: |
|
| 查看次数: |
1071 次 |
| 最近记录: |