PHP Extensión. Llamar a la función PHP existente
php-extension (1)
Así que decidí escribir una extensión para php. Todo parece estar bien, excepto que estoy atrapado en un pequeño problema.
Tengo códigos fuente php-5.4.9
. Hay un archivo ext/standard/mail.c
con una función impresionante
PHPAPI int php_mail(char *to, char *subject, char *message, char *headers, char *extra_cmd TSRMLS_DC)
En mi extensión, en acme.c
tengo incluye
...
#include "php.h"
#include "ext/standard/php_mail.h"
#include "php_ini.h"
...
Así que php_mail
siente bien y funciona bien. Pero, obviamente, quiero usar el código de mail.c
comienza en la línea 101 y termina en 189 ( http://pastie.org/5444192 5-93 líneas correspondientes en el pegado). Así que me puse a pensar en la idea (aunque en algún punto es incómodo) ¿por qué no llamar a PHP_FUNCTION(mail)
? Por el momento no pude localizar esas macros, y en realidad me gustaría saber la mejor manera de implementar la idea.
Mi ingeniero de zend interno (que es novato) me recomienda usar call_user_function
ZEND_API int call_user_function(HashTable *function_table, zval **object_pp, zval *function_name, zval *retval_ptr, zend_uint param_count, zval *params[] TSRMLS_DC);
Pero no puedo entender cómo llamarlo.
¡La pregunta! ¿Cómo (un ejemplo con función de mail
es muy bienvenido) llamar a las funciones definidas por PHP_FUNCTION
?
La forma más fácil de descubrir cómo funciona una función es buscarla en lxr.php.net. El primer ejemplo que aparece es en readline: http://lxr.php.net/xref/PHP_TRUNK/ext/readline/readline.c#474
El uso del mail
es análogo. Dados los argumentos como zvals ( to_zval
, from_zval
, msg_zval
) la llamada es muy simple:
zval *params = { to_zval, from_zval, msg_zval };
zend_uint param_count = 3;
zval *retval_ptr;
zval function_name;
INIT_ZVAL(function_name);
ZVAL_STRING(&function_name, "mail", 1);
if (call_user_function(
CG(function_table), NULL /* no object */, &function_name,
retval_ptr, param_count, params TSRMLS_CC
) == SUCCESS
) {
/* do something with retval_ptr here if you like */
}
/* don''t forget to free the zvals */
zval_ptr_dtor(&retval_ptr);
zval_dtor(&function_name);
Si aún no tiene los parámetros como zvals, puede crearlos usando MAKE_STD_ZVAL
y ZVAL_STRING
.