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 installedconfig.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)
fiCabeç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)
#endifMemó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.soCarregando 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
- Como funciona o Zend Engine
- Gerenciamento de memória e coleta de lixo
- OPcache e compilação JIT
- Escrevendo uma extensão PHP básica em C