Definindo módulos de extensão
*****************************

Uma extensão C para CPython é uma biblioteca compartilhada (por
exemplo, um arquivo ".so" no Linux, uma DLL ".pyd" no Windows), que
pode ser carregada no processo Python (por exemplo, ela é compilada
com configurações de compilador compatíveis) e que exporta uma função
de inicialização.

Para ser importável por padrão (ou seja, por
"importlib.machinery.ExtensionFileLoader"), a biblioteca compartilhada
deve estar disponível em "sys.path" e deve ser nomeada após o nome do
módulo mais uma extensão listada em
"importlib.machinery.EXTENSION_SUFFIXES".

Nota:

  A construção, o empacotamento e a distribuição de módulos de
  extensão são melhor realizados com ferramentas de terceiros e estão
  fora do escopo deste documento. Uma ferramenta adequada é o
  Setuptools, cuja documentação pode ser encontrada em
  https://setuptools.pypa.io/en/latest/setuptools.html.

Normalmente, a função de inicialização retorna uma definição de módulo
inicializada usando "PyModuleDef_Init()". Isso permite dividir o
processo de criação em várias fases:

* Antes que qualquer código substancial seja executado, o Python pode
  determinar quais recursos o módulo oferece suporte e pode ajustar o
  ambiente ou se recusar a carregar uma extensão incompatível.

* Por padrão, o próprio Python cria o objeto módulo — ou seja, faz o
  equivalente a "object.__new__()" para classes. Ele também define
  atributos iniciais como "__package__" e "__loader__".

* Depois, o objeto do módulo é inicializado usando código específico
  da extensão — o equivalente a "__init__()" em classes.

Isso é chamado de *inicialização multifásica* para diferenciá-lo do
esquema legado (mas ainda suportado) de *inicialização monofásica*, em
que a função de inicialização retorna um módulo totalmente construído.
Consulte a seção inicialização monofásica abaixo para obter detalhes.

Alterado na versão 3.5: Adicionado suporte para inicialização
multifásica (**PEP 489**).


Várias instâncias de módulo
===========================

Por padrão, módulos de extensão não são singletons. Por exemplo, se a
entrada "sys.modules" for removida e o módulo for reimportado, um novo
objeto de módulo será criado e normalmente preenchido com novos
métodos e tipos de objetos. O módulo antigo está sujeito à coleta de
lixo normal. Isso reflete o comportamento dos módulos Python puros.

Instâncias adicionais do módulo podem ser criadas em
subinterpretadores ou após a reinicialização do tempo de execução do
Python ("Py_Finalize()" e "Py_Initialize()"). Nesses casos,
compartilhar objetos Python entre instâncias do módulo provavelmente
causaria travamentos ou comportamento indefinido.

Para evitar tais problemas, cada instância de um módulo de extensão
deve ser *isolada*: alterações em uma instância não devem afetar
implicitamente as outras, e todos os estados pertencentes ao módulo,
incluindo referências a objetos Python, devem ser específicos de uma
instância específica do módulo. Consulte Isolando módulos de extensão
para obter mais detalhes e um guia prático.

Uma maneira mais simples de evitar esses problemas é levantar um erro
na inicialização repetida.

Espera-se que todos os módulos ofereçam suporte a subinterpretador, ou
então sinalizem explicitamente a falta de suporte. Isso geralmente é
obtido por isolamento ou bloqueio de inicializações repetidas, como
acima. Um módulo também pode ser limitado ao interpretador principal
usando o slot "Py_mod_multiple_interpreters".


Função de inicialização
=======================

A função de inicialização definida por um módulo de extensão tem a
seguinte assinatura:

PyObject *PyInit_modulename(void)

Seu nome deve ser "PyInit_*<nome>*", com "<nome>" substituído pelo
nome do módulo.

Para módulos com nomes com somente ASCII, a função deve ser nomeada
"PyInit_*<nome>*", com "<nome>" substituído pelo nome do módulo. Ao
usar Inicialização multifásica, nomes de módulos não ASCII são
permitidos. Neste caso, o nome da função de inicialização é
"PyInitU_*<nome>*", com "<nome>" codificado usando a codificação
*punycode* do Python com hífenes substituídos por sublinhados. Em
Python:

   def nome_func_iniciadora(nome):
       try:
           sufixo = b'_' + nome.encode('ascii')
       except UnicodeEncodeError:
           sufixo = b'U_' + nome.encode('punycode').replace(b'-', b'_')
       return b'PyInit' + sufixo

É recomendável definir a função de inicialização usando uma macro
auxiliar:

PyMODINIT_FUNC

   Declara uma função de inicialização do módulo de extensão. Esta
   macro:

   * especifica o tipo de retorno PyObject*,

   * adiciona quaisquer declarações de vinculação especiais exigidas
     pela plataforma e

   * para C++, declara a função como "extern "C"".

Por exemplo, um módulo chamado "spam" seria definido assim:

   static struct PyModuleDef spam_module = {
       .m_base = PyModuleDef_HEAD_INIT,
       .m_name = "spam",
       ...
   };

   PyMODINIT_FUNC
   PyInit_spam(void)
   {
       return PyModuleDef_Init(&spam_module);
   }

É possível exportar vários módulos de uma única biblioteca
compartilhada, definindo várias funções de inicialização. No entanto,
importá-los requer o uso de links simbólicos ou um importador
personalizado, porque por padrão apenas a função correspondente ao
nome do arquivo é encontrada. Veja a seção Multiple modules in one
library na **PEP 489** para detalhes.

A função de inicialização normalmente é o único item não "static"
definido no código-fonte C do módulo.


Inicialização multifásica
=========================

Normalmente, a função de inicialização ("PyInit_modulename") retorna
uma instância de "PyModuleDef" com "m_slots" não "NULL". Antes de ser
retornada, a instância "PyModuleDef" deve ser inicializada usando a
seguinte função:

PyObject *PyModuleDef_Init(PyModuleDef *def)
    * Parte da ABI Estável desde a versão 3.5.*

   Garante que uma definição de módulo é um objeto Python devidamente
   inicializado que reporta corretamente seu tipo e uma contagem de
   referências.

   Retorna *def* convertido para "PyObject*", ou "NULL" se ocorrer um
   erro.

   A chamada desta função é necessária para Inicialização multifásica.
   Ela não deve ser usada em outros contextos.

   Observe que o Python assume que as estruturas "PyModuleDef" são
   alocadas estaticamente. Esta função pode retornar uma nova
   referência ou uma referência emprestada; esta referência não deve
   ser liberada.

   Adicionado na versão 3.5.


Inicialização monofásica legada
===============================

Atenção:

  A inicialização monofásica é um mecanismo legado para inicializar
  módulos de extensão, com desvantagens e falhas de projeto
  conhecidas. Os autores de módulos de extensão são incentivados a
  utilizar a inicialização multifásica.

Na inicialização monofásica, a função de inicialização
("PyInit_modulename") deve criar, preencher e retornar um objeto de
módulo. Isso normalmente é feito usando "PyModule_Create()" e funções
como "PyModule_AddObjectRef()".

A inicialização monofásica difere do padrão nas seguintes maneiras:

* Módulos monofásicos são, ou melhor, *contêm*, “singletons”.

  Quando o módulo é inicializado pela primeira vez, o Python salva o
  conteúdo do "__dict__" do módulo (ou seja, normalmente, as funções e
  os tipos do módulo).

  Para importações subsequentes, o Python não chama a função de
  inicialização novamente. Em vez disso, ele cria um novo objeto de
  módulo com um novo "__dict__" e copia o conteúdo salvo para ele. Por
  exemplo, dado um módulo monofásico "_testsinglephase" [1] que define
  uma função "sum" e uma classe de exceção "error":

     >>> import sys
     >>> import _testsinglephase as one
     >>> del sys.modules['_testsinglephase']
     >>> import _testsinglephase as two
     >>> one is two
     False
     >>> one.__dict__ is two.__dict__
     False
     >>> one.sum is two.sum
     True
     >>> one.error is two.error
     True

  O comportamento exato deve ser considerado um detalhe da
  implementação do CPython.

* Para contornar o fato de que "PyInit_modulename" não aceita um
  argumento *spec*, parte do estado do mecanismo de importação é salvo
  e aplicado ao primeiro módulo adequado criado durante a chamada
  "PyInit_modulename". Especificamente, quando um submódulo é
  importado, esse mecanismo adiciona o nome do pacote pai ao nome do
  módulo.

  Uma função monofásica "PyInit_modulename" deve criar “seu” objeto de
  módulo o mais rápido possível, antes que qualquer outro objeto de
  módulo possa ser criado.

* Nomes de módulos não ASCII ("PyInitU_modulename") não são
  suportados.

* Módulos monofásicos oferecem suporte a funções de pesquisa de
  módulos como "PyState_FindModule()".

[1] "_testsinglephase" é um módulo interno usado no conjunto de
    autotestes do CPython; sua instalação pode ou não incluí-lo.
