Manufaturação industrial
Internet das coisas industrial | Materiais industriais | Manutenção e reparo de equipamentos | Programação industrial |
home  MfgRobots >> Manufaturação industrial >  >> Industrial programming >> python

Python - Programação de extensão com C

Página anteriorPróxima página
Qualquer código que você escrever usando qualquer linguagem compilada como C, C ++ ou Java pode ser integrado ou importado para outro script Python. Este código é considerado uma "extensão".

Um módulo de extensão Python nada mais é do que uma biblioteca C normal. Em máquinas Unix, essas bibliotecas geralmente terminam em .so (para objeto compartilhado). Em máquinas Windows, você normalmente vê .dll (para biblioteca vinculada dinamicamente).

Pré-requisitos para escrever extensões


Para começar a escrever sua extensão, você vai precisar dos arquivos de cabeçalho Python.

Além disso, presume-se que você tenha um bom conhecimento de C ou C ++ para escrever qualquer extensão Python usando programação C.

Primeiro, olhe para uma extensão Python


Para sua primeira olhada em um módulo de extensão Python, você precisa agrupar seu código em quatro partes -

O arquivo de cabeçalho Python.h


Você precisa incluir Python.h arquivo de cabeçalho em seu arquivo de origem C, que fornece acesso à API interna do Python usada para conectar seu módulo ao interpretador.

Certifique-se de incluir Python.h antes de qualquer outro cabeçalho que você possa precisar. Você precisa seguir as inclusões com as funções que deseja chamar do Python.

As funções C


As assinaturas da implementação C de suas funções sempre assumem uma das três formas a seguir -
 estático PyObject * MyFunction (PyObject * self, PyObject * args); estático PyObject * MyFunctionWithKeywords (PyObject * self, PyObject * args, PyObject * kwith); PyObject estático * MyFunctionWithKeywords (PyObject * self, PyObject * args, PyObject * kwith);; 

Cada uma das declarações anteriores retorna um objeto Python. Não existe algo como um vazio em Python como existe em C. Se você não quiser que suas funções retornem um valor, retorne o equivalente em C de Nenhum do Python valor. Os cabeçalhos Python definem uma macro, Py_RETURN_NONE, que faz isso para nós.

Os nomes de suas funções C podem ser o que você quiser, pois eles nunca são vistos fora do módulo de extensão. Eles são definidos como estáticos função.

Suas funções C geralmente são nomeadas combinando o módulo Python e nomes de função juntos, como mostrado aqui -
 PyObject estático *  module_func  (PyObject * self, PyObject * args) {/ * Faça suas coisas aqui. * / Py_RETURN_NONE;} 

Esta é uma função Python chamada func dentro do módulo módulo . Você colocará ponteiros para suas funções C na tabela de métodos do módulo que geralmente vem a seguir em seu código-fonte.

A tabela de mapeamento de método


Esta tabela de métodos é uma matriz simples de estruturas PyMethodDef. Essa estrutura se parece com isto -
 struct PyMethodDef {char * ml_name; PyCFunction ml_meth; int ml_flags; char * ml_doc;}; 

Aqui está a descrição dos membros desta estrutura -

Esta tabela precisa ser encerrada com uma sentinela que consiste em valores NULL e 0 para os membros apropriados.

Exemplo


Para a função definida acima, temos a seguinte tabela de mapeamento de método -
 módulo estático PyMethodDef   _métodos [] ={{" func  ", (PyCFunction)  module_func  , METH_NOARGS, NULL}, {NULL, NULL, 0, NULL}}; 

A função de inicialização


A última parte do seu módulo de extensão é a função de inicialização. Esta função é chamada pelo interpretador Python quando o módulo é carregado. É necessário que a função seja denominada Módulo init , onde Módulo é o nome do módulo.

A função de inicialização precisa ser exportada da biblioteca que você irá construir. Os cabeçalhos Python definem PyMODINIT_FUNC para incluir os encantamentos apropriados para que isso aconteça para o ambiente específico no qual estamos compilando. Tudo que você precisa fazer é usá-lo ao definir a função.

Sua função de inicialização C geralmente tem a seguinte estrutura geral -
 Módulo PyMODINIT_FUNC init   () {Py_InitModule3 ( func  ,  módulo  _methods, "docstring ...");} 

Aqui está a descrição de Py_InitModule3 função -

Juntar tudo isso se parece com o seguinte -
 # include  static PyObject *  module_func  (PyObject * self, PyObject * args) {/ * Faça suas coisas aqui. * / Py_RETURN_NONE;} módulo estático PyMethodDef   _métodos [] ={{" func  ", (PyCFunction)  module_func  , METH_NOARGS, NULL}, {NULL, NULL, 0, NULL}}; PyMODINIT_FUNC init  Módulo  () {Py_InitModule3 ( func  ,  módulo  _methods, "docstring ...");} 

Exemplo


Um exemplo simples que faz uso de todos os conceitos acima -
 # include  static PyObject * helloworld (PyObject * self) {return Py_BuildValue ("s", "Hello, Python extensions !!");} static char helloworld_docs [] ="helloworld ():Qualquer mensagem que você queira colocar aqui !! \ n"; static PyMethodDef helloworld_funcs [] ={{"helloworld", (PyCFunction) helloworld, METH_NOARGS, helloworld_docs}, {NULL}}; void inithelloworld (vazio) {Py_InitModule3 ("helloworld", helloworld_funcs, "Exemplo de módulo de extensão!");} 

Aqui, o Py_BuildValue função é usada para construir um valor Python. Salve o código acima no arquivo hello.c. Veríamos como compilar e instalar este módulo para ser chamado a partir do script Python.

Criação e instalação de extensões


Os distutils pacote torna muito fácil distribuir módulos Python, tanto Python puro quanto módulos de extensão, de uma forma padrão. Os módulos são distribuídos na forma de código-fonte e construídos e instalados por meio de um script de configuração geralmente denominado setup.py do seguinte modo.

Para o módulo acima, você precisa preparar o seguinte script setup.py -
 da configuração de importação distutils.core, Extensionsetup (name ='helloworld', version ='1.0', \ ext_modules =[Extension ('helloworld', ['hello.c'])]) 

Agora, use o seguinte comando, que executaria todas as etapas de compilação e vinculação necessárias, com os comandos e sinalizadores do compilador e do vinculador corretos e copia a biblioteca dinâmica resultante em um diretório apropriado -
 $ python setup.py install 

Em sistemas baseados em Unix, você provavelmente precisará executar este comando como root para ter permissões para gravar no diretório de pacotes do site. Isso geralmente não é um problema no Windows.

Importando extensões


Depois de instalar sua extensão, você poderá importar e chamar essa extensão em seu script Python da seguinte maneira -
 #! / usr / bin / pythonimport helloworldprint helloworld.helloworld () 

Isso produziria o seguinte resultado -
 Olá, extensões Python !! 

Passando parâmetros de função


Como você provavelmente desejará definir funções que aceitem argumentos, você pode usar uma das outras assinaturas para suas funções C. Por exemplo, a função seguinte, que aceita alguns parâmetros, seria definida assim -
 PyObject estático *  module_func  (PyObject * self, PyObject * args) {/ * Analise args e faça algo interessante aqui. * / Py_RETURN_NONE;} 

A tabela de métodos contendo uma entrada para a nova função seria semelhante a esta -
 módulo estático PyMethodDef   _métodos [] ={{" func  ", (PyCFunction)  module_func  , METH_NOARGS, NULL}, {" func  ",  module_func  , METH_VARARGS, NULL}, {NULL, NULL, 0, NULL}}; 

Você pode usar a API PyArg_ParseTuple para extrair os argumentos de um ponteiro PyObject passado para sua função C.

O primeiro argumento para PyArg_ParseTuple é o argumento args. Este é o objeto que você analisará . O segundo argumento é uma string de formato que descreve os argumentos conforme você espera que apareçam. Cada argumento é representado por um ou mais caracteres na string de formato conforme a seguir.
 PyObject estático *  module_func  (PyObject * self, PyObject * args) {int i; duplo d; char * s; if (! PyArg_ParseTuple (args, "ids", &i, &d, &s)) {return NULL; } / * Faça algo interessante aqui. * / Py_RETURN_NONE;} 

Compilar a nova versão do seu módulo e importá-la permite que você invoque a nova função com qualquer número de argumentos de qualquer tipo -
 module.func (1, s ="três", d =2.0) module.func (i =1, d =2.0, s ="três") module.func (s =" três ", d =2,0, i =1) 

Você provavelmente pode criar ainda mais variações.

O PyArg_ParseTuple Função


Aqui está a assinatura padrão para PyArg_ParseTuple função -
 int PyArg_ParseTuple (PyObject * tuple, char * format, ...) 

Esta função retorna 0 para erros e um valor diferente de 0 para sucesso. tupla é o PyObject * que era o segundo argumento da função C. Aqui formato é uma string C que descreve argumentos obrigatórios e opcionais.

Aqui está uma lista de códigos de formato para PyArg_ParseTuple função -
Código tipo C Significado
c char Uma string Python de comprimento 1 torna-se um caractere C.
d duplo Um float Python se torna um duplo C.
f float Um float Python se torna um float C.
i int Um Python int torna-se um C int.
l longo Um Python int torna-se um C longo.
L long long Um Python int torna-se um C longo
O PyObject * Obtém referência não NULL emprestada ao argumento Python.
s char * String Python sem nulos incorporados em C char *.
s # char * + int Qualquer string Python para endereço C e comprimento.
t # char * + int Buffer de segmento único somente leitura para endereço e comprimento C.
u Py_UNICODE * Python Unicode sem nulos incorporados a C.
u # Py_UNICODE * + int Qualquer endereço e comprimento Python Unicode C.
w # char * + int Leitura / gravação de buffer de segmento único no endereço C e comprimento.
z char * Como s, também aceita Nenhum (define C char * como NULL).
z # char * + int Como s #, também aceita Nenhum (define C char * como NULL).
(...) conforme ... Uma sequência Python é tratada como um argumento por item.
| Os seguintes argumentos são opcionais.
: Formato final, seguido pelo nome da função para mensagens de erro.
; Formato final, seguido por todo o texto da mensagem de erro.

Valores de retorno


Py_BuildValue recebe uma string de formato semelhante a PyArg_ParseTuple faz. Em vez de passar os endereços dos valores que você está construindo, você passa os valores reais. Aqui está um exemplo que mostra como implementar uma função add -
 static PyObject * foo_add (PyObject * self, PyObject * args) {int a; int b; if (! PyArg_ParseTuple (args, "ii", &a, &b)) {return NULL; } return Py_BuildValue ("i", a + b);} 

Isso é o que pareceria se implementado em Python -
 def add (a, b):return (a + b) 

Você pode retornar dois valores de sua função da seguinte maneira, isso seria descoberto usando uma lista em Python.
 estático PyObject * foo_add_subtract (PyObject * self, PyObject * args) {int a; int b; if (! PyArg_ParseTuple (args, "ii", &a, &b)) {return NULL; } return Py_BuildValue ("ii", a + b, a - b);} 

Isso é o que pareceria se implementado em Python -
 def add_subtract (a, b):return (a + b, a - b) 

O Py_BuildValue Função


Aqui está a assinatura padrão para Py_BuildValue função -
 PyObject * Py_BuildValue (char * format, ...) 

Aqui formato é uma string C que descreve o objeto Python a ser construído. Os seguintes argumentos de Py_BuildValue são valores C a partir dos quais o resultado é construído. O PyObject * resultado é uma nova referência.

A tabela a seguir lista as strings de código comumente usadas, das quais zero ou mais são unidas no formato de string.
Código tipo C Significado
c char Um C char se torna uma string Python de comprimento 1.
d duplo Um duplo C torna-se um float Python.
f float Um float C torna-se um float Python.
i int Um C int torna-se um Python int.
l longo Um C long torna-se um Python int.
N PyObject * Passa um objeto Python e rouba uma referência.
O PyObject * Passa um objeto Python e o INCREFA normalmente.
O & convert + void * Conversão arbitrária
s char * Char * terminado em C 0 para string Python ou NULL para Nenhum.
s # char * + int C char * e comprimento para string Python ou NULL para Nenhum.
u Py_UNICODE * Cadeia de caracteres terminada em nulo em todo o C para Python Unicode ou NULL para Nenhum.
u # Py_UNICODE * + int Cadeia de caracteres ampla de C e comprimento para Python Unicode ou NULL para Nenhum.
w # char * + int Leitura / gravação de buffer de segmento único no endereço C e comprimento.
z char * Como s, também aceita Nenhum (define C char * como NULL).
z # char * + int Como s #, também aceita Nenhum (define C char * como NULL).
(...) conforme ... Constrói tupla Python a partir de valores C.
[...] conforme ... Cria uma lista Python a partir de valores C.
{...} conforme ... Constrói dicionário Python a partir de valores C, alternando chaves e valores.

Code {...} constrói dicionários a partir de um número par de valores C, chaves e valores alternados. Por exemplo, Py_BuildValue ("{issi}", 23, "zig", "zag", 42) retorna um dicionário como o {23:'zig', 'zag':42} do Python.

python

  1. Python Renomear arquivo e diretório usando os.rename ()
  2. Python - Processamento XML
  3. Python remove duplicatas de uma lista
  4. Função round () do Python com EXEMPLOS
  5. Python - Tratamento de exceções
  6. Programação Orientada a Objetos Python