C++ library integration into PostGIS- Part II

Intégration d’une librairie C++ dans PostgreSQL -Seconde Partie

Dans le précédent article, nous avons vu qu’afin d’intégrer du C++ dans Postgres, il était nécessaire de le drapper (“wrapper”), via extern C, dans des fonctions qui, elles-mêmes, consomment les services C++. Dans cette partie, après avoir rappelé la technique de création de fonctions SQL écrites en C, nous verrons comment intégrer une librairie C++ élémentaire dans Postgres.

Construction d’une fonction SQL écrite en C

Là encore, nous allons nous inspirer pour débuter par les exemples fournis par la documentation

Première étape:

Il est nécessaire d’installer les paquets destinés au développement: sudo apt install postgresql-server-dev-14

Seconde Etape:

Afin de rendre accessible pg_config appellé par le makefile: export PATH=/usr/lib/postgresql/14/bin:$PATH

Dans le répertoire ./codes/hello_world nous créons hello_world.c:


#include "postgres.h"
#include "fmgr.h"
#include "utils/builtins.h"


PG_MODULE_MAGIC;



PG_FUNCTION_INFO_V1(hello_world);

Datum
hello_world(PG_FUNCTION_ARGS)
{
   
  PG_RETURN_TEXT_P(cstring_to_text("hello world"));
  
}

Notons au passage l’usage de la fonction cstring_to_text qui prend en charge la gestion de la mémoire occupée par le texte.

Puis toujours dans le même répertoire, nous créons le fichier hello_world.control:

comment = 'Hello_world function'
default_version = '0.0.1'
relocatable = true
module_pathname = '/home/dac/Bureau/OpenGeo/blog/codes/hello_world/hello_world'

Ainsi que le fichier hello_world–0.0.1.sql:

CREATE OR REPLACE FUNCTION
public.hello_world()
RETURNS text 
AS '/home/dac/Bureau/OpenGeo/blog/codes/hello_world/hello_world', 'hello_world'
LANGUAGE C STRICT;

Et enfin, le Makefile:


MODULES = hello_world
EXTENSION = hello_world
DATA = hello_world--0.0.1.sql
PG_CONFIG = pg_config
PGXS := $(shell $(PG_CONFIG) --pgxs)
include $(PGXS)

Un simple make suivi d’un sudo make install installent l’extension dans postgres. Pour le vérifier, depuis psql:

CREATE EXTENSION hello_world;
SELECT hello_world();

Et la phrase célèbre apparait tout simplement.

Construction d’une fonction SQL consommant une classe C++

Nous allons ici implémenter une fonction SQL hello_cpp() qui utilisera la classe MyClass définie dans l’article précédent. La plupart du code est écrit, voici l’arborescence de nos fichiers:

hello_cpp
|   hello_cpp.c
|   hello_cpp--0.0.1.sql
|   hello_cpp.control
|   Makefile
|
|___MyClass
	|    MyClass.h
	|    MyClass.cc
	|    MyWrapper.h
	|    MyWrapper.c

Nous allons, en suivant la démarche entamée précédemment, créer une librairie partagée qui au travers de l’usage du wrapper nous donnera accès à la classe.

$cd MyClass
$g++ -c -fPIC MyClass.cc -o MyClass.o
$g++ -c -fPIC MyWrapper.cc -o MyWrapper.o
$g++ -shared -o libMyWrapper.so MyWrapper.o MyClass.o

La librairie est créée. Reste à faire le pont avec Postgres:

$cd ..

Voici le code de la fonction hello_cpp.c:


#include "./MyClass/MyWrapper.h"
#include <stdio.h>
#include "postgres.h"
#include "fmgr.h"

PG_MODULE_MAGIC;


PG_FUNCTION_INFO_V1(hello_cpp);


Datum hello_cpp(PG_FUNCTION_ARGS) {

        Interface *c = newMyClass();
        MyClass_int_set(c, 3);
		int x = MyClass_int_get(c);
		deleteMyClass(c);
        PG_RETURN_INT32(x);
       
}

Celui de hello_cpp–0.0.1.sql:


CREATE OR REPLACE FUNCTION
public.hello_cpp()
RETURNS text
AS '~/Bureau/OpenGeo/blog/codes/hello_cpp/hello_cpp', 'hello_cpp'
LANGUAGE C STRICT;

Celui de hello_cpp.control:


comment = 'Hello_cpp function'
default_version = '0.0.1'
relocatable = true
module_pathname = '~/Bureau/OpenGeo/blog/codes/hello_cpp/Hello_cpp'

Et enfin le Makefile:


MODULES = hello_cpp
EXTENSION = hello_cpp
DATA = hello_cpp--0.0.1.sql
PG_CONFIG = pg_config
PGXS := $(shell $(PG_CONFIG) --pgxs)

PG_LDFLAGS := -lMyWrapper -L./MyClass -Wl,-rpath=/home/dac/Bureau/OpenGeo/blog/codes/hello_cpp/MyClass

include $(PGXS)

Noter la valeur de RPATH, qui permettra à Postgres d’accéder à libMyWrapper.so dans le répertoire dans lequel nous l’avons créé, sans avoir à le déplacer dans le conventionnel /usr/local/pgsql/lib qui contient les librairies destinées à Postgres.

Pour tester cette installation:

$ make
$ sudo make install

Dans Psql, installer l’extension via:

create extension hello_cpp;

et un:

select hello_cpp();

renvoie bien le fameux 3.