0Pricing
PHP Academy · Aula

Escrevendo uma extensão PHP básica em C

Crie e carregue sua própria extensão nativa.

Escrevendo uma extensão PHP básica em C é uma aula grátis de PHP 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 PHP Academy, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de PHP Academy inclui 4 aulas no total.

Código Nativo no PHP

Quando o PHP puro é lento demais ou é necessário vincular uma biblioteca C, escreva uma extensão do PHP em C usando a API Zend. A extensão expõe funções e classes nativas que o PHP chama diretamente, sem sobrecarga da VM.

Esta lição cria uma extensão hello mínima de ponta a ponta: esqueleto, função, compilação, carregamento e teste.

A cadeia de ferramentas de compilação

As extensões são compiladas com o phpize do PHP, que prepara uma compilação com autoconf usando os cabeçalhos da sua instalação do PHP. Você precisa de php-dev/php-devel (que fornece phpize e php-config), além de um compilador C e make.

# Install build prerequisites (Debian/Ubuntu)
sudo apt install php-dev build-essential

# Confirm the tools exist
phpize --version
php-config --extension-dir   # where the .so will be installed

config.m4

Toda extensão precisa de um config.m4 que registre uma opção de compilação e declare os arquivos de código-fonte. O phpize o utiliza para gerar o script de configuração.

dnl config.m4 for the 'hello' extension
PHP_ARG_ENABLE([hello],
  [whether to enable hello support],
  [AS_HELP_STRING([--enable-hello], [Enable hello])],
  [no])

if test "$PHP_HELLO" != "no"; then
  PHP_NEW_EXTENSION(hello, hello.c, $ext_shared)
fi

Cabeçalhos da extensão

O código-fonte C inclui os cabeçalhos do Zend/PHP e declara o ponto de entrada do módulo. php.h inclui a API principal; ext/standard/info.h é usado para a saída de phpinfo(). Toda extensão define um zend_module_entry.

/* hello.c — includes */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "php.h"
#include "ext/standard/info.h"
#include "hello_arginfo.h"   /* generated from stub */

Especificações de informações de argumentos

O PHP moderno gera metadados de argumentos a partir de um arquivo .stub.php. Você escreve a assinatura da função em uma sintaxe semelhante à do PHP; gen_stub.php produz hello_arginfo.h. Isso mantém precisas as informações de reflexão e de tipos.

<?php
// hello.stub.php — describes the native function's signature
/** @generate-class-entries */

function hello_greet(string $name): string {}
?>

Implementando a função

Uma função nativa é uma função C marcada com PHP_FUNCTION. Você analisa os argumentos recebidos com macros ZEND_PARSE_PARAMETERS e retorna valores por meio de macros RETURN_*. Aqui, construímos uma cadeia de caracteres de saudação.

/* hello.c — the native function */
PHP_FUNCTION(hello_greet)
{
    char *name;
    size_t name_len;

    ZEND_PARSE_PARAMETERS_START(1, 1)
        Z_PARAM_STRING(name, name_len)
    ZEND_PARSE_PARAMETERS_END();

    /* Build "Hello, <name>!" into a new zend_string */
    zend_string *result = strpprintf(0, "Hello, %s!", name);
    RETURN_STR(result);   /* hands ownership to the engine */
}

A entrada do módulo

O zend_module_entry reúne tudo: nome, versão, a tabela de funções (proveniente das informações de argumentos) e os ganchos do ciclo de vida (MINIT, RINIT, MINFO). ZEND_GET_MODULE exporta o símbolo de entrada que o carregador procura.

/* hello.c — module wiring */
zend_module_entry hello_module_entry = {
    STANDARD_MODULE_HEADER,
    "hello",                 /* extension name */
    ext_functions,           /* function table from arginfo */
    NULL,                    /* MINIT  (module startup)  */
    NULL,                    /* MSHUTDOWN */
    NULL,                    /* RINIT  (per-request)     */
    NULL,                    /* RSHUTDOWN */
    PHP_MINFO(hello),        /* phpinfo section */
    "0.1.0",
    STANDARD_MODULE_PROPERTIES
};

#ifdef COMPILE_DL_HELLO
ZEND_GET_MODULE(hello)
#endif

Memória: emalloc versus malloc

Dentro de uma extensão, aloque memória com duração da requisição usando emalloc/efree (rastreada pelo gerenciador de memória do Zend e liberada ao final da requisição) — não use malloc bruto. Para alocações persistentes (entre requisições), use pemalloc. Retornar uma zend_string por meio de RETURN_STR transfere a propriedade para o mecanismo, que a libera.

/* Request-scoped buffer the engine will clean up on error/shutdown */
char *buf = emalloc(64);
/* ... use buf ... */
efree(buf);

/* Persistent allocation surviving the request (rare) */
/* char *cfg = pemalloc(128, 1);  ...  pefree(cfg, 1); */

Compilando

A compilação clássica em três etapas: use phpize para criar a estrutura inicial, ./configure com sua opção de habilitação e, em seguida, make. Lembre-se de executar gen_stub.php primeiro para produzir o cabeçalho de informações de argumentos.

# Generate arginfo from the stub
php /path/to/php-src/build/gen_stub.php hello.stub.php

# Scaffold + configure + compile
phpize
./configure --enable-hello
make

# Result lands in modules/hello.so
ls -la modules/hello.so

Carregando e testando

Carregue o .so compilado com -d extension=... (ou adicione-o a um arquivo ini). Em seguida, chame a função nativa do PHP exatamente como uma função integrada. Este é o aspecto do seu script de teste/verificação depois que a extensão é instalada.

<?php
// After:  php -d extension=./modules/hello.so test.php
if (!extension_loaded('hello')) {
    fwrite(STDERR, "hello extension not loaded\n");
    exit(1);
}

echo hello_greet('Zend') . PHP_EOL;   // Hello, Zend!
var_dump(extension_loaded('hello'));  // bool(true)
?>

Quando (não) escrever uma extensão

Extensões nativas exigem manutenção: falhas de memória em C, recompilações para cada versão secundária do PHP e quebra da ABI. Antes de optar por código nativo, considere FFI (chamar bibliotecas C do PHP sem compilar uma extensão) ou a otimização em PHP puro. Recorra a uma extensão C quando precisar de velocidade máxima, integração profunda com o mecanismo ou de encapsular uma biblioteca C complexa de forma limpa.

<?php
// FFI alternative: call a C library directly, no extension build
$ffi = FFI::cdef(
    "int abs(int);",   // declare the symbol
    "libc.so.6"
);
echo $ffi->abs(-42) . PHP_EOL;   // 42
?>

Verificação rápida

Dentro de uma extensão, qual alocador deve manter a memória com duração da requisição?

Recapitulação

Você criou uma extensão C mínima: config.m4 registra a compilação, um .stub.php gera informações de argumentos, PHP_FUNCTION implementa a lógica, analisando argumentos com ZEND_PARSE_PARAMETERS e retornando por meio de RETURN_STR, e um zend_module_entry conecta os ganchos do ciclo de vida. Compile com phpize → configure → make, carregue o .so e teste a partir do PHP. Use emalloc para a memória da requisição — e considere FFI antes de optar por código nativo.

Perguntas Frequentes

A aula “Escrevendo uma extensão PHP básica em C” é grátis?

Sim — o texto completo de “Escrevendo uma extensão PHP básica em C” é 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 PHP Academy, atualize para CoddyKit PRO. O curso de PHP Academy inclui 4 aulas no total.

O que vou aprender em “Escrevendo uma extensão PHP básica em C”?

Crie e carregue sua própria extensão nativa. Você pratica PHP 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 PHP Academy?

Nenhuma experiência prévia é necessária. PHP 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 “Escrevendo uma extensão PHP básica em C”?

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 PHP Academy?

Sim. Cada aula de PHP 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. Como funciona o Zend Engine
  2. Gerenciamento de memória e coleta de lixo
  3. OPcache e compilação JIT
  4. Escrevendo uma extensão PHP básica em C
← Voltar para PHP Academy