0Pricing
Python Academy · Aula

Escrita de um módulo de extensão C para Python

Crie uma extensão .so simples usando a API Python/C.

Escrita de um módulo de extensão C para Python é uma aula grátis de Python Academy no CoddyKit. Esta é a aula 4 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de Python Academy, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de Python Academy inclui 4 aulas no total.

Anatomia de uma extensão C

Uma extensão C mínima contém: funções de métodos, uma tabela de métodos, uma estrutura de definição do módulo e um ponto de entrada PyInit_.

// myext.c skeleton
#include <Python.h>

static PyObject* say_hello(PyObject* self, PyObject* args) {
    Py_RETURN_NONE;
}

static PyMethodDef methods[] = {
    {"say_hello", say_hello, METH_NOARGS, "Print hello"},
    {NULL, NULL, 0, NULL}
};

static struct PyModuleDef module = {
    PyModuleDef_HEAD_INIT, "myext", NULL, -1, methods
};

PyMODINIT_FUNC PyInit_myext(void) {
    return PyModule_Create(&module);
}

Análise de argumentos

PyArg_ParseTuple(args, "ii", &a, &b) analisa argumentos Python e os transforma em variáveis C. Códigos de formato: i=int, d=double, s=char*, O=PyObject*.

static PyObject* add(PyObject* self, PyObject* args) {
    int a, b;
    if (!PyArg_ParseTuple(args, "ii", &a, &b))
        return NULL;
    return PyLong_FromLong(a + b);
}

Retorno de valores

Crie valores de retorno Python com: PyLong_FromLong, PyFloat_FromDouble, PyUnicode_FromString, Py_BuildValue.

// Return a Python tuple (int, float)
static PyObject* stats(PyObject* self, PyObject* args) {
    int n = 10;
    double avg = 5.0;
    return Py_BuildValue("(id)", n, avg);
    // Py_BuildValue format: i=int d=double s=str
}

Contagem de referências

Cada PyObject* tem uma contagem de referências. Utilize Py_INCREF/Py_DECREF com cuidado. Os valores retornados pelas funções C transferem a propriedade para quem chama (referências transferidas).

static PyObject* make_list(PyObject* self, PyObject* args) {
    PyObject* lst = PyList_New(3);
    for (int i = 0; i < 3; i++) {
        // PyList_SET_ITEM steals the reference:
        PyList_SET_ITEM(lst, i, PyLong_FromLong(i));
    }
    return lst;   // caller owns the list
}

Lançamento de exceções

Utilize PyErr_SetString(PyExc_ValueError, "msg") para lançar uma exceção Python a partir de C e, em seguida, retorne NULL.

static PyObject* safe_div(PyObject* self, PyObject* args) {
    int a, b;
    if (!PyArg_ParseTuple(args, "ii", &a, &b)) return NULL;
    if (b == 0) {
        PyErr_SetString(PyExc_ZeroDivisionError, "division by zero");
        return NULL;
    }
    return PyLong_FromLong(a / b);
}

setup.py para extensões C

Utilize setuptools.Extension para declarar os arquivos de código-fonte C. Compile com python setup.py build_ext --inplace.

# setup.py
from setuptools import setup, Extension

setup(
    name="myext",
    ext_modules=[
        Extension(
            "myext",
            sources=["myext.c"],
            extra_compile_args=["-O2"],
        )
    ]
)
# python setup.py build_ext --inplace
# import myext; myext.add(3, 4)

Uso da extensão compilada

Depois de compilada, importe a extensão como qualquer módulo Python. O Python a encontra procurando por myext.so (ou .pyd no Windows).

# After: python setup.py build_ext --inplace
import myext
print(myext.add(3, 4))        # 7
print(myext.safe_div(10, 2))  # 5
# myext.safe_div(1, 0)         # ZeroDivisionError

Argumentos nomeados

Utilize PyArg_ParseTupleAndKeywords com uma lista de palavras-chave para aceitar argumentos nomeados em funções C.

static char* kwargs[] = {"x", "y", NULL};

static PyObject* hypot_c(PyObject* self,
                          PyObject* args,
                          PyObject* kw) {
    double x, y;
    if (!PyArg_ParseTupleAndKeywords(args, kw, "dd",
                                     kwargs, &x, &y))
        return NULL;
    return PyFloat_FromDouble(sqrt(x*x + y*y));
}

Constantes no nível do módulo

Adicione constantes inteiras ou de texto ao módulo em PyInit_ usando PyModule_AddIntConstant.

PyMODINIT_FUNC PyInit_myext(void) {
    PyObject* m = PyModule_Create(&module);
    if (!m) return NULL;
    PyModule_AddIntConstant(m, "VERSION", 1);
    PyModule_AddStringConstant(m, "AUTHOR", "Alice");
    return m;
}

Liberação do GIL

Envolva o trabalho realizado em C puro com Py_BEGIN_ALLOW_THREADS / Py_END_ALLOW_THREADS para permitir que outras threads Python sejam executadas enquanto o código C é executado.

static PyObject* heavy(PyObject* self, PyObject* args) {
    long n;
    if (!PyArg_ParseTuple(args, "l", &n)) return NULL;
    long result;
    Py_BEGIN_ALLOW_THREADS
        result = slow_c_computation(n);  // GIL released
    Py_END_ALLOW_THREADS
    return PyLong_FromLong(result);
}

Testes da extensão

Teste extensões C por meio da interface Python usando pytest. Nenhuma ferramenta especial de testes em C é necessária.

# test_myext.py
import pytest
import myext

def test_add(): assert myext.add(3, 4) == 7
def test_zero_div():
    with pytest.raises(ZeroDivisionError):
        myext.safe_div(1, 0)

Verificação rápida

O que uma função de extensão C deve retornar para indicar que uma exceção Python foi definida?

Recapitulação

Uma extensão C precisa de: funções de métodos (analisam argumentos e retornam PyObject*), uma tabela de métodos, uma estrutura de definição do módulo e PyInit_name(). Lance exceções definindo-as com PyErr_SetString e retornando NULL. Libere o GIL para trabalhos realizados em C puro.

Perguntas Frequentes

A aula “Escrita de um módulo de extensão C para Python” é grátis?

Sim — o texto completo de “Escrita de um módulo de extensão C para Python” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de Python Academy, atualize para CoddyKit PRO. O curso de Python Academy inclui 4 aulas no total.

O que vou aprender em “Escrita de um módulo de extensão C para Python”?

Crie uma extensão .so simples usando a API Python/C. Você pratica Python Academy com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.

Preciso ter experiência prévia para começar Python Academy?

Nenhuma experiência prévia é necessária. Python Academy no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 4 de 4.

Quanto tempo leva a aula “Escrita de um módulo de extensão C para Python”?

A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.

Posso escrever e executar código nesta aula de Python Academy?

Sim. Cada aula de Python Academy inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.

Todas as aulas deste curso

  1. Por que extensões C? Casos de uso e compensações
  2. ctypes: chamando bibliotecas C do Python
  3. cffi: interface de funções externas em C
  4. Escrita de um módulo de extensão C para Python
← Voltar para Python Academy