eXe eXe - 2 months ago 15
C++ Question

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

I have tried without success to create a C-language function in PostgreSQL from a module that depends on another DLL in Windows.

For example, let's suppose I want to create the

sum
function that adds two numbers returned by the
number
function that is in its own DLL.

The code for
number.h
is:

#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


and the code for
number.cpp
is:

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


The code for
sum.cpp
is:

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"


Suppossing that PostgreSQL is installed on
C:\Program Files\PostgreSQL\9.5
, I create
number.dll
and
sum.dll
using this
build.bat
file:

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


Then I copy both DLLs to
C:\Program Files\PostgreSQL\9.5\lib
and write the SQL for creating the function in
sum.sql
:

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


After running
psql -U postgres -f sum.sql
, I get the following error:

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.


Note that this error is different from a "file not found" error. It seems that PostgreSQL finds the file, but does not recognize it as a valid module. However, if I create a static library of
num.cpp
instead and link it against
sum.dll
, then the function is created successfully. In other words, PostgreSQL loads the module only if it contains all the code it needs.

Why is this happening and how could I make PostgreSQL to know about
number.dll
when creating the
sum
function?

eXe eXe
Answer

The directories of the dependent DLLs must exist in PATH before PostgreSQL server is started.

Go to:

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

Open it and add the full path of all directories where the dependent DLLs reside. Restart the PostgreSQL server and done, psql will execute the C-module successfully.