domingo, 18 de março de 2018

Criando uma API em C para usar com CFFI - PostgreSQL

Uma lib bem legal do Postgres é a libpq.

Instalação no Debian 7, 8 e 9:

sudo apt update && sudo apt install libpq-dev


Ela pode ser usada com C ou C++.

Pequeno exemplo em C:
Includes: libpq-fe.h, stdio.h, stdlib.h, locale.h.

#define URL_CONN "dbname=mydatabase host=xx.xx.xx.xx user=postgres password=secret" 

typedef struct { 
    int n_rows;
    int n_cols; 
    char ** col_names;   
    PGresult *result;    
    PGconn * conn;
} Pq_reasult;

void pq_execute_query(char * sql){  
    setlocale(LC_ALL, "");
    Pq_reasult * pq = (Pq_reasult *) malloc(sizeof(Pq_reasult));
    pq->conn = PQconnectdb(URL_CONN); 

    if (PQstatus(pq->conn) == CONNECTION_BAD) {
        puts("Falha ao conectar ao Posgres!");
        exit(0);
    }
    
    PGresult * res = PQexec(pq->conn, sql);
    pq->result = res;
    
    if (PQresultStatus(pq->result) != PGRES_TUPLES_OK) {
        puts("0 linhas retornadas!"); 
    }     
    pq->n_rows = PQntuples(pq->result);
    pq->n_cols = PQnfields(pq->result); 

    if(pq->result != NULL){
        int row, col;  
        char * arr_res[pq->n_rows][pq->n_cols]; 
        
        for (row = 0; row < pq->n_rows; row++) {
            for (col = 0; col < pq->n_cols; col++) { 
                arr_res[row][col] = PQgetvalue(pq->result, row, col);
            } 
        }

        printf("Retornadas %d colunas.\n", (size_t)sizeof(arr_res[0]) /sizeof(*arr_res[0]));
        printf("Retornadas %d linhas.\n", (size_t)sizeof(arr_res) /sizeof(*arr_res)); 
        
   
        char * arr[pq->n_cols];
        for (col = 0; col < pq->n_cols; col++) {
            arr[col] = PQfname(pq->result, col); 
        }
        pq->col_names = &arr[0]; 
        
        int c;
        for(c = 0; c < pq->n_cols; c++){
            printf("%s\t", pq->col_names[c]);            
        }
        puts("");
        puts("==========================");
        
        for (row = 0; row < pq->n_rows; row++) {
            for (col = 0; col < pq->n_cols; col++) {
                printf("%s\t", arr_res[row][col]);
            }
            puts("");
        }

        puts("==========================");
    }
    PQclear(pq->result);
    PQfinish(pq->conn);  
} 


int main(void) {             

    return (EXIT_SUCCESS);
}
 
Vamos dar o nome do arquivo .c de "pg_foo.c".
Para linkar, no terminal digite:
$ gcc -c pg_foo.c -I /usr/include/postgresql/ -Wall -fPIC



A opção "-Wall -fPIC" é para que a lib gerada seja dinâmica. Não tem como compilar ela de modo estático. Vamos compilar:
$ gcc -shared -o libpq_query.dll pg_foo.o -I /usr/include/postgresql/ -lpq

Funciona tanto no Windows com MinGW como no Linux.

Vamos consumir com CFFI para usar com PyPy.
Baixando o PyPy:
$ wget https://bitbucket.org/pypy/pypy/downloads/pypy2-v5.10.0-linux64.tar.bz2

Extraindo:
$ tar jxf ./pypy2-v5.10.0-linux64.tar.bz2 

Vamos jogar na opt:
$ sudo mv ./pypy2-v5.10.0-linux64 /opt/pypy





Adicionar o PyPy ao PATH, no /etc/profile inclua:
export PATH=/opt/pypy/bin:$PATH




De um source:
$ source /etc/profile




Instalar o pip no PyPy para simplificar as coisas:
$ cd /opt/pypy/bin/
$ curl -O https://bootstrap.pypa.io/get-pip.py
$ sudo pypy get-pip.py

Instalando o CFFI:
sudo pypy -m pip install cffi

E finalmente:

import cffi
 
ffi = cffi.FFI()
ffi.cdef("void pq_execute_query(char * sql);") 
C = ffi.dlopen("./libpq_query.dll")

C.pq_execute_query(b" SELECT * FROM conta_contabil LIMIT 20;")

Nenhum comentário:

Postar um comentário

Criando uma API em C para usar com CFFI - PostgreSQL

Uma lib bem legal do Postgres é a libpq . Instalação no Debian 7, 8 e 9: sudo apt update && sudo apt install libpq-dev Ela po...