Scrivere un'estensione PHP di base in C
Crei e carichi una sua estensione nativa
Scrivere un'estensione PHP di base in C è una lezione PHP Academy gratuita su CoddyKit. Questa è la lezione 4 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento PHP Academy, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso PHP Academy include 4 lezioni in totale.
Codice nativo in PHP
Quando il solo PHP è troppo lento o deve collegarsi a una libreria C, può scrivere una estensione PHP in C usando la Zend API. L'estensione espone funzioni e classi native che PHP chiama direttamente, senza overhead della VM.
Questa lezione crea un'estensione hello minimale dall'inizio alla fine: scheletro, funzione, compilazione, caricamento e test.
La toolchain di build
Le estensioni vengono compilate con phpize di PHP, che prepara una compilazione basata su autoconf usando gli header della versione di PHP installata. Sono necessari php-dev/php-devel (che forniscono phpize e php-config), oltre a un compilatore C e a 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
Ogni estensione richiede un config.m4 che registra un flag di compilazione e dichiara i file sorgente. phpize lo usa per generare lo script configure.
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)
fiHeader dell'estensione
Il codice sorgente C include gli header Zend/PHP e dichiara l'entry del modulo. php.h include l'API principale; ext/standard/info.h viene usato per l'output di phpinfo(). Ogni estensione definisce un 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 */Stub di arginfo
PHP moderno genera i metadati degli argomenti da un file .stub.php. Si scrive la firma della funzione usando una sintassi simile a PHP; gen_stub.php produce hello_arginfo.h. In questo modo le informazioni di reflection e sui tipi rimangono accurate.
<?php
// hello.stub.php — describes the native function's signature
/** @generate-class-entries */
function hello_greet(string $name): string {}
?>Implementazione della funzione
Una funzione nativa è una funzione C contrassegnata con PHP_FUNCTION. Si analizzano gli argomenti in ingresso con le macro ZEND_PARSE_PARAMETERS e si restituiscono i valori tramite le macro RETURN_*. Qui costruiamo una stringa di saluto.
/* 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 */
}L'entry del modulo
L'entry zend_module_entry collega tutti gli elementi: nome, versione, tabella delle funzioni (proveniente da arginfo) e hook del ciclo di vita (MINIT, RINIT, MINFO). ZEND_GET_MODULE esporta il simbolo dell'entry che il loader cerca.
/* 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)
#endifMemoria: emalloc e malloc
All'interno di un'estensione, allochi la memoria con durata della richiesta usando emalloc/efree (tracciata dal Zend Memory Manager e liberata al termine della richiesta), non il semplice malloc. Per le allocazioni persistenti (tra richieste) usi pemalloc. Restituire una zend_string tramite RETURN_STR trasferisce la proprietà al motore, che la 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); */Compilazione
La classica compilazione in tre passaggi: phpize per predisporre la struttura, ./configure con il flag di abilitazione, infine make. Ricordi di eseguire prima gen_stub.php per produrre l'header arginfo.
# 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.soCaricamento e test
Carichi il file .so compilato con -d extension=... (oppure lo aggiunga a un file ini). Quindi chiami la funzione nativa da PHP proprio come una funzione integrata. Ecco l'aspetto del Suo script di test/verifica una volta installata l'estensione.
<?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 (non) scriverne una
Le estensioni native comportano costi di manutenzione: bug di memoria in C, ricompilazioni per ogni versione minor di PHP e incompatibilità dell'ABI. Prima di ricorrere al codice nativo, consideri FFI (per chiamare librerie C da PHP senza compilare un'estensione) oppure l'ottimizzazione in puro PHP. Scelga un'estensione C quando servono la massima velocità, una profonda integrazione con il motore o un wrapper pulito per una libreria C complessa.
<?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 rapida
All'interno di un'estensione, quale allocatore dovrebbe gestire la memoria con durata della richiesta?
Riepilogo
Ha creato un'estensione C minimale: config.m4 registra la compilazione, un file .stub.php genera l'arginfo, PHP_FUNCTION implementa la logica analizzando gli argomenti con ZEND_PARSE_PARAMETERS e restituendo il risultato tramite RETURN_STR, mentre un zend_module_entry collega gli hook del ciclo di vita. Compili con phpize → configure → make, carichi il file .so e verifichi il funzionamento da PHP. Usi emalloc per la memoria della richiesta e consideri FFI prima di scegliere il codice nativo.
Domande Frequenti
La lezione «Scrivere un'estensione PHP di base in C» è gratuita?
Sì — il testo completo di «Scrivere un'estensione PHP di base in C» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso PHP Academy, passa a CoddyKit PRO. Il corso PHP Academy include 4 lezioni in totale.
Cosa imparerò in «Scrivere un'estensione PHP di base in C»?
Crei e carichi una sua estensione nativa Eserciti PHP Academy con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.
Ho bisogno di esperienza per iniziare PHP Academy?
Non è richiesta alcuna esperienza precedente. PHP Academy su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 4 di 4.
Quanto tempo richiede la lezione «Scrivere un'estensione PHP di base in C»?
La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.
Posso scrivere ed eseguire codice in questa lezione PHP Academy?
Sì. Ogni lezione PHP Academy include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.
Tutte le lezioni di questo corso
- Come funziona Zend Engine
- Gestione della memoria e garbage collection
- OPcache e compilazione JIT
- Scrivere un'estensione PHP di base in C