4. Construindo Extensões C e C++
********************************

Uma extensão C para CPython é uma biblioteca compartilhada (por
exemplo, um arquivo ".so" no Linux, ".pyd" no Windows), que exporta
uma *função de inicialização*.

Para ser importável, a biblioteca compartilhada deve estar disponível
em "PYTHONPATH", e deve ser nomeada após o nome do módulo, com uma
extensão apropriada. Ao usar distutils, o nome do arquivo correto é
gerado automaticamente.

A função de inicialização tem a assinatura:

PyObject* PyInit_modulename(void)

Ela retorna um módulo totalmente inicializado ou uma instância de
"PyModuleDef". Veja Initializing C modules para detalhes.

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

   def initfunc_name(name):
       try:
           suffix = b'_' + name.encode('ascii')
       except UnicodeEncodeError:
           suffix = b'U_' + name.encode('punycode').replace(b'-', b'_')
       return b'PyInit' + suffix

É 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.


4.1. Construindo extensões C e C ++ com distutils
=================================================

Módulos de extensão podem ser construídos usando distutils, que está
incluído no Python. Visto que distutils também suporta a criação de
pacotes binários, os usuários não precisam necessariamente de um
compilador e distutils para instalar a extensão.

Um pacote distutils contém um script guia "setup.py". Este é um
arquivo Python simples, que, no caso mais simples, pode ter a seguinte
aparência:

   from distutils.core import setup, Extension

   module1 = Extension('demo',
                       sources = ['demo.c'])

   setup (name = 'PackageName',
          version = '1.0',
          description = 'This is a demo package',
          ext_modules = [module1])

Com este:file:*setup.py* e um arquivo "demo.c", executando

   python setup.py build

vai compilar "demo.c", e produzir um módulo de extensão chamado "demo"
no diretório "build". Dependendo do sistema, o arquivo do módulo vai
terminar em um subdiretório "build/lib.system", e pode ter um nome
como "demo.so" ou "demo.pyd".

No "setup.py", toda a execução é realizada chamando a função "setup".
Isso leva um número variável de argumentos nomeados, dos quais o
exemplo acima usa apenas um subconjunto. Especificamente, o exemplo
especifica meta-informação para construir pacotes e especifica o
conteúdo do pacote. Normalmente, um pacote conterá módulos adicionais,
como módulos-fonte Python, documentação, subpacotes etc. Consulte a
documentação do distutils em Distribuindo Módulos Python (Versão
legada) para aprender mais sobre os recursos do distutils; esta seção
explica apenas a construção de módulos de extensão.

É comum pré-computar argumentos para "setup()", para melhor estruturar
o script guia. No exemplo acima, o argumento "ext_modules" para
"setup()" é uma lista de módulos de extensão, cada um dos quais é uma
instância de "Extension". No exemplo, a instância define uma extensão
chamada "demo" que é construída compilando um único arquivo fonte,
"demo.c".

Em muitos casos, construir uma extensão é mais complexo, uma vez que
definições de pré-processador adicionais e bibliotecas podem ser
necessárias. Isso é demonstrado no exemplo abaixo.

   from distutils.core import setup, Extension

   module1 = Extension('demo',
                       define_macros = [('MAJOR_VERSION', '1'),
                                        ('MINOR_VERSION', '0')],
                       include_dirs = ['/usr/local/include'],
                       libraries = ['tcl83'],
                       library_dirs = ['/usr/local/lib'],
                       sources = ['demo.c'])

   setup (name = 'PackageName',
          version = '1.0',
          description = 'This is a demo package',
          author = 'Martin v. Loewis',
          author_email = 'martin@v.loewis.de',
          url = 'https://docs.python.org/extending/building',
          long_description = '''
   This is really just a demo package.
   ''',
          ext_modules = [module1])

Neste exemplo, "setup()" é chamado com meta-informação adicional, o
que é recomendado quando os pacotes de distribuição precisam ser
construídos. Para a extensão em si, especifica definições de
pré-processador, diretórios de inclusão, diretórios de biblioteca e
bibliotecas. Dependendo do compilador, distutils passa essas
informações de maneiras diferentes para o compilador. Por exemplo, no
Unix, isso pode resultar nos comandos de compilação

   gcc -DNDEBUG -g -O3 -Wall -Wstrict-prototypes -fPIC -DMAJOR_VERSION=1 -DMINOR_VERSION=0 -I/usr/local/include -I/usr/local/include/python2.2 -c demo.c -o build/temp.linux-i686-2.2/demo.o

   gcc -shared build/temp.linux-i686-2.2/demo.o -L/usr/local/lib -ltcl83 -o build/lib.linux-i686-2.2/demo.so

Essas linhas são apenas para fins de demonstração; Os usuários de
distutils devem confiar que distutils acertará as invocações.


4.2. Distribuindo seus módulos de extensão
==========================================

When an extension has been successfully build, there are three ways to
use it.

Os usuários finais normalmente desejam instalar o módulo, eles fazem
isso executando

   python setup.py install

Os mantenedores do módulo devem produzir pacotes fonte; para fazer
isso, eles executam:

   python setup.py sdist

Em alguns casos, arquivos adicionais precisam ser incluídos em uma
distribuição fonte; isso é feito através de um arquivo "MANIFEST.in";
veja Specifying the files to distribute para detalhes.

If the source distribution has been build successfully, maintainers
can also create binary distributions. Depending on the platform, one
of the following commands can be used to do so.

   python setup.py bdist_wininst
   python setup.py bdist_rpm
   python setup.py bdist_dumb
