如何使PostgreSQL加载依赖于DLL的C模块?

时间:2016-07-21 00:47:42

标签: c++ postgresql visual-c++ dll

我试图在一个依赖于Windows中另一个DLL的模块中在PostgreSQL中创建一个C语言函数,但没有成功。

例如,假设我想创建sum函数,该函数添加由自己的DLL中的number函数返回的两个数字。

number.h的代码是:

#ifndef NUMBER_H
#define NUMBER_H

#ifdef NUMBER_EXPORTS
#define NUMBER_API __declspec(dllexport)
#else
#define NUMBER_API __declspec(dllimport)
#endif

extern "C" NUMBER_API int number();

#endif

并且number.cpp的代码是:

#include "number.h"
extern "C" int number() { return 1; }

sum.cpp的代码是:

extern "C" {

#include <postgres.h>
#include <fmgr.h>
#include <utils/geo_decls.h>
#include "number.h"

#ifdef PG_MODULE_MAGIC
PG_MODULE_MAGIC;
#endif

__declspec(dllexport) PG_FUNCTION_INFO_V1(sum);

Datum sum(PG_FUNCTION_ARGS)
{
    int32 a {number()};
    int32 b {number()};
    int32 result {a + b};
    PG_RETURN_INT32(result);
}

} // extern "C"

假设PostgreSQL安装在C:\Program Files\PostgreSQL\9.5上,我使用此number.dll文件创建sum.dllbuild.bat

SET PG_DIR=C:\Program Files\PostgreSQL\9.5
SET PG_INCLUDES=/I%PG_DIR%\include /I%PG_DIR%\include\server /I%PG_DIR%\include\server\port\win32
CL number.cpp /EHsc /MD /DNUMBER_EXPORTS /LD
CL sum.cpp /EHsc /MD %PG_INCLUDES% /LD /link number.lib

然后我将两个DLL复制到C:\Program Files\PostgreSQL\9.5\lib并编写SQL以在sum.sql中创建函数:

CREATE OR REPLACE FUNCTION sum() RETURNS void AS
'sum'
LANGUAGE C STRICT;

运行psql -U postgres -f sum.sql后,出现以下错误:

psql:sum.sql:3: ERROR:  could not load library "C:/Program Files/PostgreSQL/9.5/lib/sum.dll": The specified module could not be found.

请注意,此错误与“找不到文件”错误不同。似乎PostgreSQL找到了该文件,但并未将其识别为有效模块。但是,如果我创建了num.cpp的静态库并将其链接到sum.dll,则会成功创建该函数。换句话说,只有当PostgreSQL包含所需的所有代码时,它才会加载模块。

为什么会发生这种情况?如何在创建number.dll函数时让PostgreSQL了解sum

1 个答案:

答案 0 :(得分:1)

在启动PostgreSQL服务器之前,依赖DLL的目录必须存在于PATH中。

转到:

Control Panel
 System and Security
  System
   Advanced System Settings
    Advanced
     Environment Variables
      Path

打开它并添加依赖DLL所在的所有目录的完整路径。重新启动PostgreSQL服务器并完成,psql将成功执行C模块。