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.