0Pricing
PHP Academy · Lección

Escritura de una extensión básica de PHP en C

Compile y cargue su propia extensión nativa

Escritura de una extensión básica de PHP en C es una lección gratuita de PHP Academy en CoddyKit. Esta es la lección 4 de 4. Puedes leer la lección completa abajo gratuitamente — luego la practicas en el navegador con un editor de código integrado y un tutor de IA 24/7. Forma parte de la ruta de aprendizaje de PHP Academy, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de PHP Academy incluye 4 lecciones en total.

Código nativo en PHP

Cuando PHP puro es demasiado lento o necesita vincular una biblioteca de C, puede escribir una extensión de PHP en C usando la API de Zend. La extensión expone funciones y clases nativas que PHP llama directamente, sin la sobrecarga de la VM.

En esta lección se crea una extensión hello mínima de principio a fin: esqueleto, función, compilación, carga y prueba.

La cadena de herramientas de compilación

Las extensiones se compilan con el phpize de PHP, que prepara una compilación basada en autoconf usando las cabeceras de su instalación de PHP. Necesita php-dev/php-devel (proporciona phpize y php-config), además de un compilador de C y 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 extensión necesita un archivo config.m4 que registre una opción de compilación y declare los archivos de código fuente. phpize lo utiliza para generar el script de configuración.

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

Cabeceras de la extensión

El código fuente en C incluye las cabeceras de Zend/PHP y declara la entrada del módulo. php.h incorpora la API principal; ext/standard/info.h se utiliza para la salida de phpinfo(). Toda extensión define 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 */

Stubs de arginfo

PHP moderno genera los metadatos de los argumentos a partir de un archivo .stub.php. Usted escribe la firma de la función con una sintaxis similar a PHP; gen_stub.php produce hello_arginfo.h. Esto mantiene precisas la reflexión y la información de tipos.

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

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

Implementación de la función

Una función nativa es una función de C marcada con PHP_FUNCTION. Los argumentos recibidos se analizan mediante macros de ZEND_PARSE_PARAMETERS y los valores se devuelven mediante macros de RETURN_*. Aquí se construye una cadena de saludo.

/* 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 */
}

Entrada del módulo

La entrada zend_module_entry lo reúne todo: el nombre, la versión, la tabla de funciones (a partir de arginfo) y los hooks del ciclo de vida (MINIT, RINIT, MINFO). ZEND_GET_MODULE exporta el símbolo de entrada que busca el cargador.

/* 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

Memoria: emalloc frente a malloc

Dentro de una extensión, asigne memoria con duración de la solicitud mediante emalloc/efree (gestionada por el administrador de memoria de Zend y liberada al finalizar la solicitud), no mediante malloc sin procesar. Para asignaciones persistentes (entre solicitudes), use pemalloc. Devolver un zend_string mediante RETURN_STR transfiere la propiedad al motor, que lo 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); */

Compilación

La compilación clásica consta de tres pasos: phpize para preparar la estructura inicial, ./configure con su opción de activación y, después, make. Recuerde ejecutar primero gen_stub.php para generar la cabecera de 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.so

Carga y pruebas

Cargue el archivo .so compilado con -d extension=... (o añádalo a un archivo ini). Después, llame a la función nativa desde PHP exactamente igual que a una función integrada. Este es el aspecto de su script de prueba/verificación una vez instalada la extensión.

<?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)
?>

Cuándo (no) escribir una

Las extensiones nativas tienen un coste de mantenimiento: errores de memoria en C, recompilaciones para cada versión menor de PHP y rupturas de ABI. Antes de optar por código nativo, considere FFI (llamar a bibliotecas de C desde PHP sin compilar una extensión) u optimizar PHP puro. Recurra a una extensión de C cuando necesite la máxima velocidad, una integración profunda con el motor o encapsular limpiamente una biblioteca de C compleja.

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

Comprobación rápida

Dentro de una extensión, ¿qué asignador se debe utilizar para gestionar la memoria con duración de la solicitud?

Resumen

Ha creado una extensión mínima en C: config.m4 registra la compilación, un .stub.php genera arginfo, PHP_FUNCTION implementa la lógica analizando los argumentos con ZEND_PARSE_PARAMETERS y devolviendo el resultado mediante RETURN_STR, y una zend_module_entry conecta los hooks del ciclo de vida. Compile con phpize → configure → make, cargue el archivo .so y haga pruebas desde PHP. Use emalloc para la memoria de la solicitud y considere FFI antes de comprometerse con código nativo.

Preguntas frecuentes

¿La lección «Escritura de una extensión básica de PHP en C» es gratis?

Sí — el texto completo de «Escritura de una extensión básica de PHP en C» es gratis para leer aquí en la web. Para practicarla de forma interactiva (editor de código integrado y tutor de IA 24/7) y desbloquear el resto del curso de PHP Academy, actualiza a CoddyKit PRO. El curso de PHP Academy incluye 4 lecciones en total.

¿Qué aprenderé en «Escritura de una extensión básica de PHP en C»?

Compile y cargue su propia extensión nativa Practicas PHP Academy con código real que ejecutas directamente en el navegador, y un tutor de IA 24/7 responde tus preguntas mientras trabajas en la lección.

¿Necesito experiencia previa para empezar PHP Academy?

No se requiere experiencia previa. PHP Academy en CoddyKit está estructurado para principiantes hasta estudiantes avanzados, así que puedes empezar aquí o desde el inicio y avanzar a tu ritmo. Esta es la lección 4 de 4.

¿Cuánto tiempo toma la lección «Escritura de una extensión básica de PHP en C»?

La mayoría de las lecciones de CoddyKit toman alrededor de 5–10 minutos. Cada una es compacta e interactiva, así que avanzas constantemente y retomas exactamente por donde dejaste en la web y la app.

¿Puedo escribir y ejecutar código en esta lección de PHP Academy?

Sí. Cada lección de PHP Academy incluye un editor de código integrado, así que escribes y ejecutas código real directamente en tu navegador y obtienes retroalimentación instantánea de IA — sin configuración local necesaria.

Todas las lecciones de este curso

  1. Cómo funciona Zend Engine
  2. Gestión de memoria y recolección de basura
  3. OPcache y compilación JIT
  4. Escritura de una extensión básica de PHP en C
← Volver a PHP Academy