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

How to make PostgreSQL to load a C-module that depends on a DLL?

本文关键字:模块 DLL 依赖于 何使 PostgreSQL 加载      更新时间:2023-10-16

我曾尝试从依赖于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 FilesPostgreSQL9.5 上,我使用此build.bat文件创建number.dllsum.dll

SET PG_DIR=C:Program FilesPostgreSQL9.5
SET PG_INCLUDES=/I%PG_DIR%include /I%PG_DIR%includeserver /I%PG_DIR%includeserverportwin32
CL number.cpp /EHsc /MD /DNUMBER_EXPORTS /LD
CL sum.cpp /EHsc /MD %PG_INCLUDES% /LD /link number.lib

然后我将两个 DLL 复制到C:Program FilesPostgreSQL9.5lib并编写用于在 sum.sql 中创建函数的 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只有在它包含所需的所有代码时才加载模块。

为什么会发生这种情况,我怎样才能让PostgreSQL在创建sum函数时了解number.dll

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

转到:

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

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