在写PHP扩展时,你可能对那些无处不在的宏感到困惑不已,本文将为你揭开这个秘密:
/* __header_here__ */
#ifdef HAVE_CONFIG_H
#include “config.h”
#endif
#include “php.h”
#include “php_globals.h”
#include “php_ini.h”
#include “ext/standard/info.h”
#include “php_myext.h”
#ifdef ZTS
#include “TSRM.h”
#endif
/* If you declare any globals in php_myext.h uncomment this:
ZEND_DECLARE_MODULE_GLOBALS(myext)
*/
/* True global resources - no need for thread safety here */
static int le_myext;
/* {{{ myext_functions[]
*
* Every user visible function must have an entry in myext_functions[].
*/
zend_function_entry myext_functions[] = {
PHP_FE(confirm_myext_compiled, NULL) /* For testing, remove later. */
PHP_FE(junk, NULL) /* My First PHP extension function. */
PHP_FE(extend_test, NULL) /* … */
PHP_FE(sample_reference_a, php_sample_retref_arginfo)
PHP_FE(sample_byref_calltime, NULL)
PHP_FALIAS(sample_byref_compiletime, sample_byref_calltime, php_sample_byref_arginfo)
/* __function_entries_here__ */
{NULL, NULL, NULL} /* Must be the last line in myext_functions[] */
};
/* }}} */
/* {{{ myext_module_entry
*/
zend_module_entry myext_module_entry = {
#if ZEND_MODULE_API_NO >= 20010901
STANDARD_MODULE_HEADER,
#endif
“myext”,
myext_functions,
PHP_MINIT(myext),
PHP_MSHUTDOWN(myext),
PHP_RINIT(myext), /* Replace with NULL if there’s nothing to do at request start */
PHP_RSHUTDOWN(myext), /* Replace with NULL if there’s nothing to do at request end */
PHP_MINFO(myext),
#if ZEND_MODULE_API_NO >= 20010901
“0.1″, /* Replace with version number for your extension */
#endif
STANDARD_MODULE_PROPERTIES
};
/* }}} */
#ifdef COMPILE_DL_MYEXT
ZEND_GET_MODULE(myext)
#endif
/* {{{ PHP_INI
*/
/* Remove comments and fill if you need to have entries in php.ini
PHP_INI_BEGIN()
STD_PHP_INI_ENTRY(”myext.global_value”, “42″, PHP_INI_ALL, OnUpdateLong, global_value, zend_myext_globals, myext_globals)
STD_PHP_INI_ENTRY(”myext.global_string”, “foobar”, PHP_INI_ALL, OnUpdateString, global_string, zend_myext_globals, myext_globals)
PHP_INI_END()
*/
/* }}} */
/* {{{ php_myext_init_globals
*/
/* Uncomment this function if you have INI entries
static void php_myext_init_globals(zend_myext_globals *myext_globals)
{
myext_globals->global_value = 0;
myext_globals->global_string = NULL;
}
*/
/* }}} */
/* {{{ PHP_MINIT_FUNCTION
*/
PHP_MINIT_FUNCTION(myext)
{
/* If you have INI entries, uncomment these lines
REGISTER_INI_ENTRIES();
*/
return SUCCESS;
}
/* }}} */
/* {{{ PHP_MSHUTDOWN_FUNCTION
*/
PHP_MSHUTDOWN_FUNCTION(myext)
{
/* uncomment this line if you have INI entries
UNREGISTER_INI_ENTRIES();
*/
return SUCCESS;
}
/* }}} */
/* Remove if there’s nothing to do at request start */
/* {{{ PHP_RINIT_FUNCTION
*/
PHP_RINIT_FUNCTION(myext)
{
return SUCCESS;
}
/* }}} */
/* Remove if there’s nothing to do at request end */
/* {{{ PHP_RSHUTDOWN_FUNCTION
*/
PHP_RSHUTDOWN_FUNCTION(myext)
{
return SUCCESS;
}
/* }}} */
/* {{{ PHP_MINFO_FUNCTION
*/
PHP_MINFO_FUNCTION(myext)
{
php_info_print_table_start();
php_info_print_table_header(2, “myext support”, “enabled”);
php_info_print_table_row (2, “myext.enable”, “1″);
php_info_print_table_end();
/* Remove comments if you have entries in php.ini
DISPLAY_INI_ENTRIES();
*/
}
/* }}} */
/* {{{ proto junk (string arg)
Return a string of the parameters */
#pragma warning (disable: 4101)
PHP_FUNCTION(junk)
{
char * arg = NULL;
int arg_len, len;
char * strg;
long l;
double d = 0.0;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, “sl|d”, &arg, &arg_len, &l, &d) == FAILURE) {
return;
}
php_printf (”%s<br>”, arg);
php_printf (”%d<br>”, l);
php_printf (”%f<br>”, d);
if (return_value_ptr == NULL) {
php_printf (”junk: return value_ptr is null”);
}
RETURN_STRINGL(arg, arg_len, 1);
}
/* {{{ proto showglobal(string arg)
Show global variables */
#if (PHP_MAJOR_VERSION > 5) || (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 0)
PHP_FUNCTION(extend_test)
{
#ifdef ARRAY_RANGE_TEST
if (return_value_used) {
int i;
/* Return an array from 0 - 999 */
array_init(return_value);
for(i = 0; i < 1000; i++) {
add_next_index_long(return_value, i);
}
return;
} else {
/* Save yourself the effort */
php_error_docref(NULL TSRMLS_CC, E_ALL,
“Static return-only function called without processing output”);
RETURN_NULL();
}
#endif
#ifdef RETURN_REFERENCE_TEST
/*
*
*/
zval **a_ptr, *a;
/* Fetch $a from the global symbol table */
if (zend_hash_find(&EG(symbol_table), “a”, sizeof(”a”), (void**)&a_ptr) == SUCCESS) {
php_printf (”GLOBALS['a'] found!”);
a = *a_ptr;
} else {
/* $GLOBALS['a'] doesn’t exist yet, create it */
php_printf (”GLOBALS['a'] not found, create it”);
ALLOC_INIT_ZVAL(a);
zend_hash_add(&EG(symbol_table), “a”, sizeof(”a”), &a,
sizeof(zval*), NULL);
}
/* Toss out the old return_value */
if (return_value_ptr == NULL) {
php_printf (”return_value_ptr invalid”);
return_value_ptr = (zval **)&return_value_ptr;
}
zval_ptr_dtor((zval **)&return_value);
if (!a->is_ref && a->refcount > 1) {
/* $a is in a copy-on-write reference set
* It must be separated before it can be used
*/
zval *newa;
MAKE_STD_ZVAL(newa);
*newa = *a;
zval_copy_ctor(newa);
newa->is_ref = 0;
newa->refcount = 1;
zend_hash_update(&EG(symbol_table), “a”, sizeof(”a”), &newa,
sizeof(zval*), NULL);
a = newa;
}
/* Promote to full-reference and increase refcount */
a->is_ref = 1;
a->refcount ++;
*return_value_ptr = a;
#endif /* RETURN_REFERENCE_TEST */
#define RETURN_CALLTIME_BYREF_TEST 1
#if (RETURN_CALLTIME_BYREF_TEST)
zval *a;
int addtl_len = sizeof(” (modified by ref!)”) - 1;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, “z”, &a) == FAILURE) {
RETURN_NULL();
}
if (!a->is_ref) {
/* parameter was not passed by reference,
* leave without doing anything
*/
return;
}
/* Make sure the variable is a string */
convert_to_string(a);
/* Enlarge a’s buffer to hold the additional data */
Z_STRVAL_P(a) = erealloc(Z_STRVAL_P(a),
Z_STRLEN_P(a) + addtl_len + 1);
memcpy(Z_STRVAL_P(a) + Z_STRLEN_P(a),
” (modified by ref!)”, addtl_len + 1);
Z_STRLEN_P(a) += addtl_len;
#endif
}
#endif /* PHP >= 5.1.0 */
#if (PHP_MAJOR_VERSION > 5) || (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 0)
PHP_FUNCTION(sample_reference_a)
{
zval **a_ptr, *a;
/* Fetch $a from the global symbol table */
if (zend_hash_find(&EG(symbol_table), “a”, sizeof(”a”),
(void**)&a_ptr) == SUCCESS) {
a = *a_ptr;
} else {
/* $GLOBALS['a'] doesn’t exist yet, create it */
ALLOC_INIT_ZVAL(a);
zend_hash_add(&EG(symbol_table), “a”, sizeof(”a”), &a,
sizeof(zval*), NULL);
}
if (return_value_used) {
php_printf(”sample_reference_a: return_value_used = true.<br>”);
}
/* Toss out the old return_value */
if (!return_value_ptr) {
php_printf (”sample_reference_a: return_value_ptr is null.”);
RETURN_NULL();
}
zval_ptr_dtor(return_value_ptr);
if (!a->is_ref && a->refcount > 1) {
/* $a is in a copy-on-write reference set
* It must be separated before it can be used
*/
zval *newa;
MAKE_STD_ZVAL(newa);
*newa = *a;
zval_copy_ctor(newa);
newa->is_ref = 0;
newa->refcount = 1;
zend_hash_update(&EG(symbol_table), “a”, sizeof(”a”), &newa,
sizeof(zval*), NULL);
a = newa;
}
/* Promote to full-reference and increase refcount */
a->is_ref = 1;
a->refcount++;
*return_value_ptr = a;
}
#endif /* PHP >= 5.1.0 */
PHP_FUNCTION(sample_byref_calltime)
{
zval *a;
int addtl_len = sizeof(” (modified by ref!)”) - 1;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, “z”, &a) == FAILURE) {
RETURN_NULL();
}
if (!a->is_ref) {
/* parameter was not passed by reference,
* leave without doing anything
*/
return;
}
/* Make sure the variable is a string */
convert_to_string(a);
/* Enlarge a’s buffer to hold the additional data */
Z_STRVAL_P(a) = erealloc(Z_STRVAL_P(a),
Z_STRLEN_P(a) + addtl_len + 1);
memcpy(Z_STRVAL_P(a) + Z_STRLEN_P(a),
” (modified by ref!)”, addtl_len + 1);
Z_STRLEN_P(a) += addtl_len;
}
/* Remove the following function when you have succesfully modified config.m4
so that your module can be compiled into PHP, it exists only for testing
purposes. */
/* Every user-visible function in PHP should document itself in the source */
/* {{{ proto string confirm_myext_compiled(string arg)
Return a string to confirm that the module is compiled in */
PHP_FUNCTION(confirm_myext_compiled)
{
char *arg = NULL;
int arg_len, len;
char *strg;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, “s”, &arg, &arg_len) == FAILURE) {
return;
}
len = spprintf(&strg, 0, “Congratulations! You have successfully modified ext/%.78s/config.m4. Module %.78s is now compiled into PHP.”, “myext”, arg);
RETURN_STRINGL(strg, len, 0);
}
/* }}} */
/* The previous line is meant for vim and emacs, so it can correctly fold and
unfold functions in source code. See the corresponding marks just before
function definition, where the functions purpose is also documented. Please
follow this convention for the convenience of others editing your code.
*/
/* __function_stubs_here__ */
/*
* Local variables:
* tab-width: 4
* c-basic-offset: 4
* End:
* vim600: noet sw=4 ts=4 fdm=marker
* vim<600: noet sw=4 ts=4
*/
在这些宏被扩展后,其代码看起来是这样的:
static
zend_arg_info php_sample_retref_arginfo[] = { { ((void *)0), 0, ((void *)0), 0, 0, 0, 0, 1, 0 },
};
#line 25 “php_myext.h”
static
zend_arg_info php_sample_byref_arginfo[] = { { ((void *)0), 0, ((void *)0), 0, 0, 0, 0, 0, -1 },
{ ((void *)0), 0, ((void *)0), 0, 0, 0, 1, 0, 0 },
};
#line 35 “php_myext.h”
int zm_startup_myext(int type, int module_number , void ***tsrm_ls);
int zm_shutdown_myext(int type, int module_number , void ***tsrm_ls);
int zm_activate_myext(int type, int module_number , void ***tsrm_ls);
int zm_deactivate_myext(int type, int module_number , void ***tsrm_ls);
void zm_info_myext(zend_module_entry *zend_module , void ***tsrm_ls);
void zif_confirm_myext_compiled(int ht, zval *return_value, zval **return_value_ptr, zval *this_ptr, int return_value_used , void ***tsrm_ls);
void zif_junk(int ht, zval *return_value, zval **return_value_ptr, zval *this_ptr, int return_value_used , void ***tsrm_ls);
void zif_extend_test(int ht, zval *return_value, zval **return_value_ptr, zval *this_ptr, int return_value_used , void ***tsrm_ls);
void zif_sample_byref_calltime(int ht, zval *return_value, zval **return_value_ptr, zval *this_ptr, int return_value_used , void ***tsrm_ls);
void zif_sample_reference_a(int ht, zval *return_value, zval **return_value_ptr, zval *this_ptr, int return_value_used , void ***tsrm_ls);
zend_function_entry myext_functions[] = {
{ “confirm_myext_compiled”, zif_confirm_myext_compiled, ((void *)0), (zend_uint) (sizeof(((void *)0))/sizeof(struct _zend_arg_info)-1), 0 },
{ “junk”, zif_junk, ((void *)0), (zend_uint) (sizeof(((void *)0))/sizeof(struct _zend_arg_info)-1), 0 },
{ “extend_test”, zif_extend_test, ((void *)0), (zend_uint) (sizeof(((void *)0))/sizeof(struct _zend_arg_info)-1), 0 },
{ “sample_reference_a”, zif_sample_reference_a, php_sample_retref_arginfo, (zend_uint) (sizeof(php_sample_retref_arginfo)/sizeof(struct _zend_arg_info)-1), 0 },
{ “sample_byref_calltime”, zif_sample_byref_calltime, ((void *)0), (zend_uint) (sizeof(((void *)0))/sizeof(struct _zend_arg_info)-1), 0 },
{ “sample_byref_compiletime”, zif_sample_byref_calltime, php_sample_byref_arginfo, (zend_uint) (sizeof(php_sample_byref_arginfo)/sizeof(struct _zend_arg_info)-1), 0 },
{((void *)0), ((void *)0), ((void *)0)}
};
zend_module_entry myext_module_entry = {
sizeof(zend_module_entry), 20060613, ZEND_DEBUG, 1, ((void *)0), ((void *)0),
#line 47 “myext.c”
“myext”,
myext_functions,
zm_startup_myext,
zm_shutdown_myext,
zm_activate_myext,
zm_deactivate_myext,
zm_info_myext,
“0.1″,
#line 57 “myext.c”
0, ((void *)0), ((void *)0), ((void *)0), ((void *)0), 0, 0, ((void *)0), 0
};
__declspec(dllexport) zend_module_entry *get_module(void) { return &myext_module_entry; }
#line 64 “myext.c”
int zm_startup_myext(int type, int module_number , void ***tsrm_ls)
{
return 0;
}
int zm_shutdown_myext(int type, int module_number , void ***tsrm_ls)
{
return 0;
}
int zm_activate_myext(int type, int module_number , void ***tsrm_ls)
{
return 0;
}
int zm_deactivate_myext(int type, int module_number , void ***tsrm_ls)
{
return 0;
}
void zm_info_myext(zend_module_entry *zend_module , void ***tsrm_ls)
{
php_info_print_table_start();
php_info_print_table_header(2, “myext support”, “enabled”);
php_info_print_table_row (2, “myext.enable”, “1″);
php_info_print_table_end();
}
#pragma warning (disable: 4101)
void zif_junk(int ht, zval *return_value, zval **return_value_ptr, zval *this_ptr, int return_value_used , void ***tsrm_ls)
{
char * arg = ((void *)0);
int arg_len, len;
char * strg;
long l;
double d = 0.0;
if (zend_parse_parameters((ht) , tsrm_ls, “sl|d”, &arg, &arg_len, &l, &d) == -1) {
return;
}
php_printf (”%s<br>”, arg);
php_printf (”%d<br>”, l);
php_printf (”%f<br>”, d);
if (return_value_ptr == ((void *)0)) {
php_printf (”junk: return value_ptr is null”);
}
{ { char *__s=(arg); int __l=arg_len; (return_value)->value.str.len = __l; (return_value)->value.str.val = (1?_estrndup((__s), (__l) ):__s); (return_value)->type = 6; }; return; };
}
void zif_extend_test(int ht, zval *return_value, zval **return_value_ptr, zval *this_ptr, int return_value_used , void ***tsrm_ls)
{
zval *a;
int addtl_len = sizeof(” (modified by ref!)”) - 1;
if (zend_parse_parameters((ht) , tsrm_ls, “z”, &a) == -1) {
{ { (*return_value).type = 0; }; return;};
}
if (!a->is_ref) {
return;
}
if ((a)->type != 6) { _convert_to_string((a) ); };
(*a).value.str.val =
_erealloc(((*a).value.str.val), ((*a).value.str.len + addtl_len + 1), 0 );
memcpy((*a).value.str.val + (*a).value.str.len,
” (modified by ref!)”, addtl_len + 1);
(*a).value.str.len += addtl_len;
#line 260 “myext.c”
}
#line 263 “myext.c”
void zif_sample_reference_a(int ht, zval *return_value, zval **return_value_ptr, zval *this_ptr, int return_value_used , void ***tsrm_ls)
{
zval **a_ptr, *a;
if (zend_hash_find(&(((zend_executor_globals *) (*((void ***) tsrm_ls))[((executor_globals_id)-1)])->symbol_table), “a”, sizeof(”a”),
(void**)&a_ptr) == 0) {
a = *a_ptr;
} else {
(a) = (zval *) _emalloc((sizeof(zval)) ); *a = zval_used_for_init;;;
_zend_hash_add_or_update(&(((zend_executor_globals *) (*((void ***) tsrm_ls))[((executor_globals_id)-1)])->symbol_table), “a”, sizeof(”a”), &a, sizeof(zval*), ((void *)0), (1<<1) );
}
if (return_value_used) {
php_printf(”sample_reference_a: return_value_used = true.<br>”);
}
if (!return_value_ptr) {
php_printf (”sample_reference_a: return_value_ptr is null.”);
{ { (*return_value).type = 0; }; return;};
}
_zval_ptr_dtor((return_value_ptr) );
if (!a->is_ref && a->refcount > 1) {
zval *newa;
(newa) = (zval *) _emalloc((sizeof(zval)) ); (newa)->refcount = 1; (newa)->is_ref = 0;;;
*newa = *a;
_zval_copy_ctor((newa) );
newa->is_ref = 0;
newa->refcount = 1;
_zend_hash_add_or_update(&(((zend_executor_globals *) (*((void ***) tsrm_ls))[((executor_globals_id)-1)])->symbol_table), “a”, sizeof(”a”), &newa, sizeof(zval*), ((void *)0), (1<<0) );
a = newa;
}
a->is_ref = 1;
a->refcount++;
*return_value_ptr = a;
}
#line 311 “myext.c”
void zif_sample_byref_calltime(int ht, zval *return_value, zval **return_value_ptr, zval *this_ptr, int return_value_used , void ***tsrm_ls)
{
zval *a;
int addtl_len = sizeof(” (modified by ref!)”) - 1;
if (zend_parse_parameters((ht) , tsrm_ls, “z”, &a) == -1) {
{ { (*return_value).type = 0; }; return;};
}
if (!a->is_ref) {
return;
}
if ((a)->type != 6) { _convert_to_string((a) ); };
(*a).value.str.val =
_erealloc(((*a).value.str.val), ((*a).value.str.len + addtl_len + 1), 0 );
memcpy((*a).value.str.val + (*a).value.str.len,
” (modified by ref!)”, addtl_len + 1);
(*a).value.str.len += addtl_len;
}
void zif_confirm_myext_compiled(int ht, zval *return_value, zval **return_value_ptr, zval *this_ptr, int return_value_used , void ***tsrm_ls)
{
char *arg = ((void *)0);
int arg_len, len;
char *strg;
if (zend_parse_parameters((ht) , tsrm_ls, “s”, &arg, &arg_len) == -1) {
return;
}
len = spprintf(&strg, 0, “Congratulations! You have successfully modified ext/%.78s/config.m4. Module %.78s is now compiled into PHP.”, “myext”, arg);
{ { char *__s=(strg); int __l=len; (return_value)->value.str.len = __l; (return_value)->value.str.val = (0?_estrndup((__s), (__l) ):__s); (return_value)->type = 6; }; return; };
}
欲知后事如何,且听下回分解…


0 responses so far ↓
There are no comments yet...Kick things off by filling out the form below.
Leave a Comment