Higher Education Statistics in C Language
Linguagens de Programação
Docente: Professor Doutor José Jasnau Caeiro
Discente: Rafael Montegordo Félix nº 6209
Abril, 2011
Índice
Introdução ................................................................................................................................. 3
API Utilizadas ............................................................................................................................. 4
API SQLite/C .......................................................................................................................... 5
Python/C API ......................................................................................................................... 5
Funções ..................................................................................................................................... 6
Qsort() – Funções de Comparação ........................................................................................ 6
Funções Callback ................................................................................................................... 6
void cleanFile() ...................................................................................................................... 7
PyObject* nDocentesPerYear(PyObject* orderBy)............................................................... 7
PyObject* listInstYear(PyObject* yearList) ........................................................................... 7
PyObject* nDocentesPerInstPerYear(PyObject* yearList).................................................... 8
PyObject* nDocentesPerDegreePerYear(PyObject* yearList) .............................................. 8
PyObject* nDocentesPerDegreePerInstPerYear(PyObject* yearList) .................................. 8
listDegreeHolder(PyObject* yearList, PyObject* degree) .................................................... 9
teacherHiringPerInst() ........................................................................................................... 9
GPROF ..................................................................................................................................... 10
Conclusão ................................................................................................................................ 11
Bibliografia .............................................................................................................................. 12
Introdução
Este trabalho tem como objectivo a criação de um módulo que poderá ser mais tarde utilizado
através de um programa criado na linguagem Python.
Para a criação deste módulo foi utilizada a linguagem C, uma linguagem imperativa cujos seus
pontos de design foram para ele ser compilado, fornecendo acesso de baixo nível à memória e
baixos requerimentos do hardware, tornando-a assim uma linguagem bastante rápida.
Para a criação deste módulo foi também utilizada a biblioteca de sqlite para a linguagem C,
para que fosse possível a recolha da informação de uma base de dados.
Foi também necessário consultar a documentação da Python/C API para que fosse possível
retornar os resultados obtidos no módulo programado em C para o programa em Python.
Ficheiros
O programa foi dividido em ficheiros para que a sua leitura seja mais fácil.
Datacolletion.c
Neste ficheiro é possível encontrar as funções principais que geram as estatísticas e listas e as
devolvem para que possam ser utilizadas no Python. Gera também um ficheiro de texto com a
informação recolhida das várias funções executadas.
Functions.c
Contém as funções que auxiliam as funções principais, as funções que efectuam o tratamento
dos dados, como as funções de comparação utilizadas no qsort e as funções de “callback”
utilizadas pelo sqlite3_exec.
Funcoes.h
Ficheiro header (interface) do anterior. Neste ficheiro são definidas as estruturas e as funções
utilizadas pelo nosso programa indicando o cabeçalho das mesmas, sendo necessário de pois
efectuar um “include ” deste ficheiro nos que necessitarem de utilizar estas mesmas funções.
API Utilizadas
API SQLite/C
Em todas as funções que seja necessário aceder a base de dados, foi utilizada a API SQLite/C,
para poder efectuar consultas e recolher informação da base de dados.
São utilizadas três funções desta API, a função sqlite3_open para abrir a base de dados,
sqlite3_exec para efectuar a consulta e por ultimo uma função de “callback” que é executada
por cada linha de informação existente na consulta efectuada a base de dados. Esta função de
“calback” pode ser alterada de maneira a efectuar o pretendido pelo programador. Tem
também a possibilidade de receber por parâmetro um ponteiro para um variável de qualquer
tipo, para que o utilizador possa armazenar a informação e não tenha que recorrer a variáveis
globais.
Python/C API
Esta API permite que variáveis da linguagem C sejam convertidas para objectos da linguagem
Python, criando assim a possibilidade de efectuar passagem de informação entre as duas
linguagens.
Neste trabalho foram utilizadas varias funções, como por exemplo a PyList_New() que permite
criar uma lista que poderá ser utilizada no Python.
Muitas outras foram utilizadas, para converter inteiros, strings, entre outros. Toda esta
informação está disponível no site[1] do Python.
Funções
Qsort() – Funções de Comparação
Qsort() é a função utilizada para ordenar a informação. Esta função recebe como parâmetros
um array, o tamanho do array, o tipo de dados do array e uma função para efectuar a
ordenação. É utilizada em praticamente todas as outras funções, alterando-se apenas a função
de ordenação.
Neste trabalho temos 4 funções de comparação:
- comparenNumberPerYear(struct NumberPerYear *elem1, struct NumberPerYear *elem2)
- compNDocentesPerInstPerYear(struct nDocentesPerInstPerYear *elem1, struct
nDocentesPerInstPerYear *elem2)
- compNDocentesPerDegreePerInstPerYear(struct nDocentesPerDegreePerInstPerYear
*elem1, struct nDocentesPerDegreePerInstPerYear *elem2)
- PyStringCmp(PyObject** elem1, PyObject** elem2)
Nas primeiras 3 a única diferença e o tipo de elemento que recebe por parâmetro, pois para
desenvolver as funções necessárias foi utilizado estruturas para guardar os dados, e cada
função de comparação recebe uma estrutura de tipo diferente. Ambas as 3 comparam
números e organiza-os do menor para o maior.
A PyStringCmp recebe elementos de Python (PyObjects), neste caso strings, converte-os para
array de chars através da função PyString_AsString e compara as strings com recurso a função
strcmp(), organizando assim a informação por ordem alfabética. A organização por ordem
alfabética tem um pequeno erro, pois as palavras que começam com acento na primeira letra
são colocadas no fim da lista, mesmo sendo a primeira letra um ‘Á’.
Funções Callback
Como já foi referido em cima, as funções de “callback“, são utilizadas pelo sqlite3_exec para
guardar a informação da consulta á base de dados em variáveis para que seja possível a
manipulação desses dados.
Temos 4 funções de “callback”:




callbackInt(void **NotUsed, int argc, char **argv, char **azColName)
callbackPyList(void **NotUsed, int argc, char **argv, char **azColName)
callBack_NDIY(struct nDocentesPerInstPerYear **NotUsed, int argc, char **argv, char
**azColName)
callBack_NDDIY(struct nDocentesPerDegreePerInstPerYear **NotUsed, int argc, char
**argv, char **azColName)
Nas funções de “callback” a variável NotUsed, referida em todas as funções, é a variável que
nos podemos enviar para o “callback” para guardar os dados, esta variável pode ser de
qualquer tipo.
Neste caso as variáveis NotUsed são apontadores para os apontadores da variável que nós
passamos para guardar os dados. Isto é muito útil pois faz com que seja possível que na
callBack_NDIY e na callBack_NDDIY seja possível percorrer um array de estruturas, para que
possamos gravar as várias linhas de informação recolhida da base de dados, uma linha em
cada posição do array.
A função callbackInt apenas guarda a informação de um inteiro e a callbackPyList vai
introduzindo a informação numa lista de objectos Python.
void cleanFile()
Toda a informação é guardada num único ficheiro.
Esta função pode ser utilizada para limpar esse mesmo ficheiro, caso seja necessário escrever
nova informação.
PyObject* nDocentesPerYear(PyObject* orderBy)
Esta função é responsável por retornar uma lista de tuplos, onde cada tuplo contém o ano e o
número total de docentes nesse mesmo ano.
A informação é obtida através de uma consulta a base de dados, utilizando a API SQlite. Utiliza
a função callbackInt para guardar a informação numa variável.
Esta função recebe também uma string de Python que indica se o utilizador quer ordenar a
informação por número de docentes ou por ano (“NDOCENTES” – ordena pelo nº de docentes,
“” – ordena por ano).
Para efectuar esta ordenação foi utilizada a função qsort() com a função de comparação
comparenNumberPerYear.
Toda esta informação está convertida através da Python/C API para objectos de Python, para
que possa ser tratada pelo software desenvolvido na linguagem Python.
Toda a informação recolhida é também escrita num ficheiro para o utilizador poder aceder.
PyObject* listInstYear(PyObject* yearList)
Esta função retorna uma lista de tuplos, onde cada tuplo contém o ano e uma lista com todas
as instituições desse ano.
Toda esta informação está convertida através da Python/C API para objectos de Python, para
que possa ser tratada pelo software desenvolvido na linguagem Python.
Esta função recebe do software de Python uma lista de anos, para que o utilizador possa
indicar de quais ou qual o ano que pretende informação.
A função de “callback” utilizada é a callbackPyList.
Para efectuar a ordenação da informação utilizado uma aboradagem diferente, pois tínhamos
uma lista de objectos Python em vez das estruturas utilizadas nas outras funções. Foi então
necessário a criação de uma array para guardar esses objectos, sendo depois utilizada a função
qsort() com a função de comparação PyStringCmp.
Toda a informação recolhida é também escrita num ficheiro para o utilizador poder aceder.
PyObject* nDocentesPerInstPerYear(PyObject* yearList)
PyObject* nDocentesPerDegreePerYear(PyObject* yearList)
Estas funções retornam uma lista de tuplos, onde cada tuplo contém o ano, a instituição/Grau
e o número de docentes nessa instituição.
Toda esta informação está convertida através da Python/C API para objectos de Python, para
que possa ser tratada pelo software desenvolvido na linguagem Python.
Esta função recebe do software de Python uma lista de anos, para que o utilizador possa
indicar de quais ou qual o ano que pretende informação.
A função de “callback” utilizada é a callBack_NDIY.
Para efectuar a ordenação da informação, nesta função foi utilizado novamente o qsort() com
a função de comparação compNDocentesPerInstPerYear.
Toda a informação recolhida é também escrita num ficheiro para o utilizador poder aceder.
PyObject* nDocentesPerDegreePerInstPerYear(PyObject* yearList)
Esta função retorna uma lista de tuplos, onde cada tuplo contém ano, instituição, grau e
número de docente.
Para calcular o espaço a alocar em memória para o array de estruturas que guardará esta
informação foi utilizada a funcção nDegreeInstYear(yearList), que retorna um array o número
de elementos que será necessário alocar no array de estruturas por ano.
Foi efectuado também uma da referência do primeiro elemento do array de estruturas, para
poder depois no final libertar o espaço alocado.
A função de “callback” utilizada é a callBack_NDDIY.
Para efectuar a ordenação da informação, nesta função foi utilizado novamente o qsort() com
a função de comparação compNDocentesPerDegreePerInstPerYear.
Toda a informação recolhida é também escrita num ficheiro para o utilizador poder aceder.
listDegreeHolder(PyObject* yearList, PyObject* degree)
Esta função retorna uma lista de tuplos, onde cada tuplo contém ano e uma lista com onome
dos docentes que detêm aquele grau de ensino.
Tal como na função listInstYear() o método de ordenação foi novamente a criação de um array
de PyObjects para colocar os elementos da lista de Python, utilizando posteriormente a função
qsort() com a função de comparação PyStringCmp.
Toda a informação recolhida é também escrita num ficheiro para o utilizador poder aceder.
teacherHiringPerInst()
Esta função verifica em todas as instituições quais as diferenças entre o número de docentes
nos diversos anos. Para efectuar esta verificação recorre a utilização de duas funções, sendo
elas a teacherHiring(PyObject* inst) e listInstNoWrite(PyObject* year).
A função listInstNoWrite recebe como parâmetro um ano e retorna a lista de todas as
instituições. Cada elemento desta lista é depois enviado para a função teacherHiring que
recebe como parâmetro o nome de uma instituição e calcula então a diferença entre o número
de docentes da instituição por ano e retorna uma lista com toda essa informação. Esta função
escreve também os resultados obtidos num ficheiro.
Visto esta função utilizar outras para efectuar os cálculos não é necessário a utilização de
nenhuma função para ordenar, pois toda a informação já vem ordenada.
GPROF
Gprof é uma ferramenta para análise dinâmica da execução de programas escritos em
linguagem C, Fortran e Pascal. O propósito usual desse tipo de análise é determinar o quanto
de recurso computacional é consumido por cada parte do código, com o objectivo de
optimizar o tempo de execução e diminuir quando possível o consumo de memória. Essa
ferramenta pode ser usada em conjunto com o GCC.
O Gprof, como o docente referiu, utiliza bibliotecas estáticas não funcionado muito bem com
os PyObjects. Contudo muitas das funcionalidades do trabalho desenvolvido necessitam de
PyObjects para funcionar, pois existem várias funções que recebem PyLists e outros objectos
de python. Retirar todos os objectos de python do trabalho iria requerer que cria-se novas
funções que não dependessem desses mesmos objectos para funcionarem.
Conclusão
A realização deste trabalho foi bastante interessante pois nunca tinha efectuado uma
“mistura” de linguagens que são completamente diferentes, pois o C é uma linguagem de
baixo nível onde não existe objectos e Python é uma linguagem de alto nível que está
orientada para objectos.
Gostei de realizar este trabalho e aprender que é possível a interligação de várias linguagens
mesmo sendo elas bastante distintas.
Utilizando esta metodologia é possível fazer com que a linguagem de baixo nível, que
geralmente é mais rápida, efectue as consultas, efectue os cálculos, ou seja, efectue todas as
operações, para que estas sejam processadas mais rapidamente. Deixando assim para a
linguagem de alto nível a apresentação dos mesmos.
Para a realização deste trabalho foi também necessária a consulta da documentação referente
às APIs utilizadas, SQLite/C e Python/C, o que foi uma mais-valia para a nossa formação.
Quanto ao gprof, se soubesse que não iria funcionar com PyObjects teria desenvolvido todo o
trabalho de maneira diferente, para que certas funções não ficassem dependentes de destes
objectos, podendo assim efectuar uma compilação com o gprof.
Bibliografia
[1] Python/C API Reference Manual, < http://docs.python.org/c-api/>
Download

Higher Education Statistics in C Language