PHP  
downloads | documentation | faq | getting help | mailing lists | | php.net sites | links 
search for in the  
previousProtocole du d�buggeurAppeler des fonctions utilisateursnext
Last updated: Tue, 09 Jul 2002
view the printer friendly version or the printer friendly version with notes or change language to English | Brazilian Portuguese | Chinese | Czech | Dutch | Finnish | German | Hungarian | Italian | Japanese | Korean | Polish | Romanian | Russian | Spanish | Swedish | Turkish

Annexe E. D�veloppement PHP

Cr�er une fonction PHP 3

Prototypes de fonctions

Toutes les fonctions suivent le sch�ma suivant :

void php3_foo(INTERNAL_FUNCTION_PARAMETERS) {
}
M�me si votre fonction ne prend aucun argument, c'est comme cela qu'elle doit �tre appel�e.

Arguments de fonctions

Les arguments sont toujours de type val. Ce type contient un membre de type union, qui indique le type re�l d'argument. De cette fa�on, si votre fonction prend deux arguments, elle ressemble � ceci :

Exemple E-1. Argument de fonction de lecture

pval *arg1, *arg2;
if (ARG_COUNT(ht) != 2 || getParameters(ht,2,&arg1,&arg2)==FAILURE) {
   WRONG_PARAM_COUNT;
}
NOTE: Les arguments peuvent �tre pass� par valeur ou par r�f�rence. Dans les deux cas, vous devez passer &(pval *) � getParameters. Si vous voulez v�rifier que le n-i�me param�tre a �t� pass� par r�f�rence ou par valeur, vous devez utiliser la fonction ParameterPassedByReference(ht,n). Elle retournera 1 ou 0.

Lorsque vous modifiez l'un des param�tres, qu'ils soient envoy�s par r�f�rence ou par valeur, vous pouvez le passer � pval_destructor pour le r�initialiser, ou, s'il s'agit d'un tableau et que vous voulez ajouter des valeurs, vous pouvez utiliser des fonctions similaires � celles qui sont dans internal_functions.h, qui manipule return_value comme tableau.

Par ailleurs, si vous modifiez un param�tre en IS_STRING, assurez-vous que vous avez bien assign� un nouvelle cha�ne avec estrdup() et une nouvelle longueur de cha�ne. Seulement apr�s, vous pouvez modifier le type en IS_STRING. Si vous modifiez une cha�ne en IS_STRING ou IS_ARRAY vous devez d'abord appeler le destructeur pval_destructor.

Fonctions � nombre d'arguments variable

Une fonction peut prendre un nombre variable d'arguments. Si votre fonction peut prendre deux ou trois arguments, utiliser la syntaxe suivante :

Exemple E-2. Fonctions � nombre d'arguments variable

pval *arg1, *arg2, *arg3;
int arg_count = ARG_COUNT(ht);
if (arg_count < 2 || arg_count > 3 ||
    getParameters(ht,arg_count,&arg1,&arg2,&arg3)==FAILURE) {
    WRONG_PARAM_COUNT;
}

Utiliser les arguments d'une fonction

De type de chaque argument est stock� dans le champs pval. Ce champs peut prendre les valeurs suivantes :

Tableau E-1. Types de donn�es interne PHP

IS_STRINGCha�ne de caract�res
IS_DOUBLENombre � virgule flottante, en pr�cision double
IS_LONGEntier long
IS_ARRAYTableau
IS_EMPTYAucune
IS_USER_FUNCTION??
IS_INTERNAL_FUNCTION?? (Si ce type ne peut pas �tre pass� � une fonction, effacez-le)
IS_CLASS??
IS_OBJECT??

Si vous recevez un argument d'un type, et que vous voulez l'utiliser avec un autre type, ou si vous voulez simplement forcer le type, vous pouvez utiliser l'une des fonctions de conversion suivantes :

convert_to_long(arg1);
convert_to_double(arg1);
convert_to_string(arg1);
convert_to_boolean_long(arg1);
/* Si la cha�ne est "" ou "0" elle devient 0, 1 sinon */
convert_string_to_number(arg1);
/* Convertit une cha�ne en LONG ou DOUBLE suivant la cha�ne */

Ces fonctions convertissent sur place : elles ne retournent aucune valeur.

La valeur de l'argument est enregistr�e dans une union. Les membres sont :

  • IS_STRING: arg1->value.str.val

  • IS_LONG: arg1->value.lval

  • IS_DOUBLE: arg1->value.dval

Gestion de la m�moire dans une fonction

Toute la m�moire n�cessaire � une fonction doit �tre allou�e avec emalloc() ou estrdup(). Ces fonctions ont le go�t et l'odeur des fonctions C classiques malloc() et strdup(). La m�moire doit �tre lib�r�e avec efree().

Il y a deux types de m�moire dans ce programme : la m�moire qui est retourn�e � l'analyseur, et la m�moire qui n�cessaire pour le stockage temporaire dans la fonction. Lorsque vous assignez une cha�ne dans une variable qui est retourn�e � l'analyseur, assurez-vous de bien allouer la m�moire avec emalloc() ou estrdup(). Cette m�moire ne doit JAMAIS �tre lib�r�e, sauf si vous r��crivez votre original plus loin, dans la m�me fonction (mais ce n'est pas de la programmation propre).

Pour tous vos besoins en m�moire temporaire/permanante dont vous avez besoin dans vos fonctions/librairies, vous devez utiliser les fonctions emalloc(), estrdup() et efree(). Elles se comportent EXACTEMENT comme leurs homologues. Tout ce qui est cr�� avec emalloc() ou estrdup() doit �tre lib�r� avec efree() � un moment ou un autre, � moins que ce ne soit utile ailleurs dans le programme; sinon, il va y avoir une fuite de m�moire. La signification de "Elles se comportent EXACTEMENT comme leurs homologues" est que si vous lib�rez une variable qui n'a pas �t� cr��e avec emalloc() ou estrdup(), vous courez droit � au crash ("segmentation fault"). Soyez alors extr�mement prudent, et lib�rez toute votre m�moire inutilis�e.

Si vous compilez avec "-DDEBUG", PHP 3 affichera la liste de tous les appels � emalloc() et estrdup() mais jamais � efree() lorsque celui-ci intervient dans un script sp�cifi�.

Affecter une variable dans la table des symboles

Un grand nombre de macros sont disponibles pour rendre plus facile l'insertion de variables dans la table des symboles :

  • SET_VAR_STRING(name,value)

  • SET_VAR_DOUBLE(name,value)

  • SET_VAR_LONG(name,value)

Gestion de la m�moire

Soyez prudent. La valeur doit �tre plac�e dans une portion de m�moire cr��e avec malloc(), sinon le gestionnaire de m�moire essayera de lib�rer le pointeur plus tard. Ne passez aucune m�moire allou�e statiquement � SET_VAR_STRING.

Les tables des symboles de PHP 3 est une table de hash. A n'importe quel moment, &symbol_table est un pointeur sur la table principale, et active_symbol_table pointe sur la table actuellement utilis�e. (ces deux tables peuvent �tre identiques au d�marrage, ou diff�rent, suivant que vous �tes dans une fonction ou non).

Les exemples suivants utilisent 'active_symbol_table'. Vous devriez la remplacer par &symbol_table si vous voulez travailler sur la table principale. De plus, les m�mes fonctions peuvent �tre appliqu�es � des tableaux, comme expliqu� ci-dessous.

Exemple E-3. V�rification de l'existence de $foo dans la table des symboles

if (hash_exists(active_symbol_table,"foo",sizeof("foo"))) {
 // existe...
} else {
 // n'existe pas
}

Exemple E-4. Rechercher la taille d'une variable dans la table des symboles

hash_find(active_symbol_table,"foo",sizeof("foo"),&pvalue);
check(pvalue.type);
En PHP 3.0, les tableaux sont impl�ment�s en utilisant les m�mes tables de hash que les variables. Cela signifie que les deux fonctions ci-dessus peuvent �tre appel�es pour v�rifier la pr�sence de variables dans un tableau.

Si vous voulez d�finir un nouveau tableau dans la table des symboles, utilisez le code suivant.

D'abord, vous devez v�rifier qu'il n'existe pas, avec hash_exists() ou hash_find().

Puis, initialisez le tableau :

Exemple E-5. Initialisation d'un tableau

pval arr;
if (array_init(&arr) == FAILURE) { /*Initialiation �chou�e*/ };
hash_update(active_symbol_table,"foo",sizeof("foo"),&arr,sizeof(pval),NULL);
Ce code d�clare un nouveau tableau, appel� $foo, dans la table de symbole. Ce tableau est vide.

Voici comment ajouter deux nouvelles entr�es dans ce tableau :

Exemple E-6. Ajout d'entr�es dans un tableau.

pval entry;
entry.type = IS_LONG;
entry.value.lval = 5;
/* d�finit $foo["bar"] = 5 */
hash_update(arr.value.ht,"bar",sizeof("bar"),&entry,sizeof(pval),NULL);
/* d�finit $foo[7] = 5 */
hash_index_update(arr.value.ht,7,&entry,sizeof(pval),NULL);
/* d�finit la prochaine place libre dans $foo[],
 * $foo[8], qui sera 5 (comme en php2)
 */
hash_next_index_insert(arr.value.ht,&entry,sizeof(pval),NULL);
Si vous voulez modifier une valeur que vous avez ins�r� dans une table de hash, vous devez d'abord la lire dans la table. Pour �viter cette recherche, vous pouvez fournir une pval ** � la fonction d'ajout dans la table de hash, et elle modifiera la valeur � l'adresse pval *, avec la valeur donn�e. Si cette valeur est NULL, (comme dans tous les exemples ci dessus), ce param�tre sera ignor�.

hash_next_index_insert() utiliser plus ou moins la m�me logique que "$foo[] = bar;" in PHP 2.0.

Si vous construisez un tableau, pour le retourner, vous pouvez l'initialiser comme ceci :

if (array_init(return_value) == FAILURE) { �chec...; }

puis ajouter les valeurs gr�ces aux macros:

add_next_index_long(return_value,long_value);
add_next_index_double(return_value,double_value);
add_next_index_string(return_value,estrdup(string_value));

Bien s�r, si l'ajout n'est pas fait juste apr�s l'initialisation, vous devrez d'abord rechercher le tableau :

pval *arr;
if (hash_find(active_symbol_table,"foo",sizeof("foo"),(void **)&arr)==FAILURE)
{ introuvable... }
else
{ utilisez arr->value.ht... }

Notez que hash_find re�oit un pointeur sur un pointeur sur pval, et pas un pointeur sur pval.

Toutes les fonctions d'acc�s aux hash retourne TRUE (SUCCES) ou FALSE (FAILURE), except� hash_exists(), qui retourne un bool�en.

Retourne une valeur simple

Un grand nombre de macros sont disponible pour simplifier le retour des valeurs.

La macro RETURN_* fixe la valeur de retour, et termine la fonction :

  • RETURN

  • RETURN_FALSE

  • RETURN_TRUE

  • RETURN_LONG(l)

  • RETURN_STRING(s,dup) Si dup est TRUE, duplique la cha�ne.

  • RETURN_STRINGL(s,l,dup) retourne la cha�ne (s) en sp�cifiant la longueur (l).

  • RETURN_DOUBLE(d)

La macro RETVAL_* macros fixe la valeur de retour, mais ne termine pas la fonction.

  • RETVAL_FALSE

  • RETVAL_TRUE

  • RETVAL_LONG(l)

  • RETVAL_STRING(s,dup) Si dup est TRUE, duplique la cha�ne

  • RETVAL_STRINGL(s,l,dup) retourne la cha�ne (s) en sp�cifiant la longueur (l).

  • RETVAL_DOUBLE(d)

Les macros ci-dessus vont utiliser estrdup() sur les arguments pass�s. Cela vous permet de lib�rer tranquillement les arguments apr�s avoir appel� cette fonction, ou bien, utiliser de la m�moire allou�e statiquement.

Si votre fonction retourne un bool�en de succ�s/erreur, utilisez toujours RETURN_TRUE et RETURN_FALSE respectivement.

Retourner des valeurs complexes

Votre fonction peut aussi retourner des valeurs complexes, tels que des objets ou tableaux.

Retourner un objet:

  1. Appeler object_init(return_value).

  2. Remplissez les valeurs. Les fonctions utilisables sont list�es ci dessous.

  3. Eventuellement, enregistrez les fonctions pour cet objet. Afin de lire des valeurs de cet objet, la fonction doit lire dans "this", dans la table de symbole active active_symbol_table. Son type doit �tre IS_OBJECT, et c'est une table de hash basique. (i.e., vous pouvez utiliser les fonctions habituelles de .value.ht). L'enregistrement re�l peut �tre fait comme suit :

    add_method( return_value, function_name, function_ptr );

Les fonctions d'acc�s aux objets sont :

  • add_property_long( return_value, property_name, l ) - Ajoute un membre nomm� 'property_name', de type long, �gal � 'l'

  • add_property_double( return_value, property_name, d ) - Idem, ajoute un double

  • add_property_string( return_value, property_name, str ) - Idem, ajoute une cha�ne

  • add_property_stringl( return_value, property_name, str, l ) - Idem, ajoute une cha�ne de longueur 'l'.

Retournez un tableau :

  1. Appelez array_init(return_value).

  2. Remplissez les valeurs. Les fonctions disponibles sont list�es ci-dessous.

Les fonctions utilis�es pour acc�der � un tableau sont :

  • add_assoc_long(return_value,key,l) - Ajoute une entr�e associative avec la cl� 'key' et la valeur 'l', de type long

  • add_assoc_double(return_value,key,d) - Ajoute une entr�e associative avec la cl� 'key' et la valeur 'l', de type double

  • add_assoc_string(return_value,key,str,duplicate)

  • add_assoc_stringl(return_value,key,str,length,duplicate) sp�cifie la taille d'une cha�ne

  • add_index_long(return_value,index,l) - Ajoute une entr�e d'index index' avec la valeur 'l', de type long

  • add_index_double(return_value,index,d)

  • add_index_string(return_value,index,str)

  • add_index_stringl(return_value,index,str,length) - sp�cifie la longueur de la cha�ne.

  • add_next_index_long(return_value,l) - ajoute une entr�e tableau, dans le prochain offset libre, de longueur 'l', de type long

  • add_next_index_double(return_value,d)

  • add_next_index_string(return_value,str)

  • add_next_index_stringl(return_value,str,length) - sp�cifie la taille d'une cha�ne

Utiliser la liste des ressources

PHP 3.0 dispose de standards pour traiter un certains nombre de ressources. Ils remplacent tous les listes de PHP 2.0.

Fonctions accessibles :

  • php3_list_insert(ptr, type) - retourne l'identifiant 'id' de la nouvelle ressource ins�r�e.

  • php3_list_delete(id) - efface la ressource d'identifiant id

  • php3_list_find(id,*type) - retourne le pointeur de la ressource d'identifiant id, et modifie le type 'type'

Typiquement, ces fonctions sont utilis�es pour les pilotes SQL, mais elles peuvent servir n'importe quoi d'autre. Par exemple, conserver un pointeur de fichier.

La liste standard de code ressemble � ceci :

Exemple E-7. Ajouter une nouvelle ressource

RESOURCE *resource;
/* ...alloue de la m�moire pour la ressource, et l'acquiert ... */
/* Ajoute la nouvelle ressource dans la liste */
return_value->value.lval = php3_list_insert((void *) resource, LE_RESOURCE_TYPE);
return_value->type = IS_LONG;

Exemple E-8. Utiliser une ressource existante

pval *resource_id;
RESOURCE *resource;
int type;
convert_to_long(resource_id);
resource = php3_list_find(resource_id->value.lval, &type);
if (type != LE_RESOURCE_TYPE) {
    php3_error(E_WARNING,"resource index %d has the wrong type",resource_id->value.lval);
    RETURN_FALSE;
}
/* ...utiliser la ressource... */

Exemple E-9. Effacer une ressource existante

pval *resource_id;
RESOURCE *resource;
int type;
convert_to_long(resource_id);
php3_list_delete(resource_id->value.lval);
Les types de ressources doivent �tre enregistr� dans le fichier php3_list.h, dans l'�num�ration list_entry_type. En plus, il faut penser � ajouter une fonction de terminaison, pour chaque type de ressource d�fini, dans le fichier list.c, pour la fonction list_entry_destructor() (m�me si vous n'avez rien de particulier � faire lors de la terminaison, vous devez au moins ajouter un cas vide.

Utiliser la table des ressources persistantes.

PHP 3.0 dispose d'une lieu de stockage des ressources persistantes (i.e., les ressources qui doivent �tre conserv�es d'un hit � l'autre). Le premier module a utiliser cette capacit� a �t� MySQL, et mSQL suivi, ce qui fait que l'on peut se faire une impression du fonctionnement de cette fonction avec mysql.c. Les fonctions ressemblent � ceci :

php3_mysql_do_connect
php3_mysql_connect()
php3_mysql_pconnect()

L'id�e conductrice de ces modules est la suivante :

  1. Programmez tout votre module pour qu'il travaille avec les ressources standard, comme mentionn� dans la section (9).

  2. Ajoutez une autre fonction de connexion, qui v�rifie d'abord que la ressource existe dans la liste des ressources persistantes. Si c'est le cas, enregistrez cette ressource comme pour les ressources standard (et gr�ce � la premi�re �tape, cela va fonctionner imm�diatement). Si la ressource n'existe pas, cr�ez la, ajoutez la � la liste de ressources persistantes, et ajoutez la � la liste de ressources, ce qui fait que le code va fonctionner, et que le prochain appel renverra une ressource existante. Vous devez enregistrer ces fonctions avec un type diff�rent (LE_MYSQL_LINK pour les liens non persistants, et LE_MYSQL_PLINK pour les liens persistants).

Si vous jetez un oeil dans mysql.c, vous verrez que, hormis la fonction de connexion complexe, rien n'a du �tre chang� dans le module.

La m�me interface existe pour la liste des ressources standard, et pour la liste des ressources persistantes, seule la 'list' est remplac�e par 'plist':

  • php3_plist_insert(ptr, type) - retourne l'identifiant 'id' de la nouvelle ressource ins�r�e.

  • php3_plist_delete(id) - efface la ressource d'identifiant id

  • php3_plist_find(id,*type) - retourne le pointeur de la ressource d'identifiant id, et modifie le type 'type'

Cependant, il est probable que ces fonctions seront inutiles pour vous, lorsque vous essayerez d'impl�mentez un module persistant. Typiquement, on utiliser le fait que la liste de ressources persistantes est une table de hash. Par exemple, dans les modules MySQL/mSQL, lors d'un appel � pconnect(), la fonction construit une cha�ne avec l'h�te/utilisateur/mot_de_passe, et l'utilise pour enregistrer dans la table de hash. Au prochain appel, avec les m�mes h�te/utilisateur/mot_de_passe, la m�me cl� sera g�n�r�e, et la ressource associ�e sera retrouv�e.

Jusqu'� ce que la documentation s'�toffe, jetez un oeil aux fichiers mysql.c ou msql.c pour voir comment impl�mentez vos acc�s aux ressources persistantes.

Une chose importante � noter : les ressources qui sont enregistr�es dans la liste de ressource persistante ne DOIVENT PAS �tre allou�e avec le gestionnaire de m�moire PHP, c'est-�-dire qu'elles ne doivent pas �tre cr��e avec emalloc(), estrdup(), etc. Au contraire, il faut utiliser les fonctions standard malloc(), strdup(), etc. La raison est for simple : � la fin de la requ�te, la m�moire sera supprim�e par le gestionnaire. Etant donn� que les liens persistants doivent �tre conserv�s, il ne faut pas utiliser le gestionnaire de m�moire.

Lorsque vous enregistrez une ressource qui sera plac� dans la liste de ressources persistantes, il faut ajouter les destructeurs dans les deux listes de ressources, persistantes ou pas. Le destructeur de la liste de ressources non persistantes ne doit rien faire du tout, tandis que celui de la liste de ressources persistantes doit lib�rer proprement toutes les ressources acquises (m�moire, lien SQL...). Commep pour les ressources non persistantes vous DEVEZ ajouter un destructeur, m�me s'il ne fait rien. N'oubliez pas que emalloc() et compagnie ne doivent pas �tre utilis� en conjonction avec la liste de ressources persistantes, et donc, vous ne devez pas utiliser efree() non plus.

Ajouter des directives de configuration � l'ex�cution

De nombreuses caract�ristiques de PHP 3 peuvent �tre configur�e � l'�x�cution. Ces directives peuvent appara�tre dans le fichier php3.ini, ou, dans le cas du module Apache, dans le fichier .conf. L'avantage de l'avoir dans le fichier .conf, est que ces caract�ristiques peuvent �tre configur�es dossier par dossier. Cela signifie qu'un dossier peut avoir un safe mode exec dir, tandis qu'un autre en aura un autre. Cette granularit� de la configuration peut �tre extr�mement pratique lorsque le serveur supporte plusieurs serveurs virtuels.

Les �tapes de configuration d'une nouvelle directive sont :

  1. Ajouter la directive � la structure php3_ini_structure dans le fichier mod_php3.h.

  2. Dans main.c, �ditez la fonction php3_module_startup et ajoutez l'appel apropri� � cfg_get_string() ou cfg_get_long().

  3. Ajoutez la directive, ses restrictions et un commentaire dans la structure php3_commands du fichier mod_php3.c. Notez la partie restrictions RSRC_CONF sont des directives qui ne peuvent �tre disponibles que dans le fichier de configuration Apache. Toutes les directives OR_OPTIONS peuvent �tre plac�es n'importe o�, y compris dans un fichier .htaccess.

  4. Soit dans php3take1handler(), soit dans php3flaghandler(), ajoutez l'entr�e appropri�e pour votre directive.

  5. Dans la section de configuration, de _php3_info(), dans le fichier functions/info.c, vous devez ajouter votre configuration.

  6. Finalement, vous devez utiliser votre configuration quelque part. Elle sera accessible par php3_ini.directive.

User Contributed Notes
D�veloppement PHP
add a note about notes
[email protected]
09-Aug-1999 01:50

One thing i've noted is that hash_find() and hash_exists() don't work with php4.


if(hash_find(arr->value.ht, "key",
sizeof("key"), (void *)tmp) == SUCCESS) {

stuff...

} else {

other stuff...

}


The code that is written using that won't load into PHP. Use _php3_hash_find() and _php3_hash_exists() instead:


if(_php3_hash_exists(arr->value.ht, "key", sizeof("key"), (void *)tmp) {

stuff

} else {

more stuff

}


It works with both, although the "(void *)" needs to be changed to "(void **) for php4.

[email protected]
29-Sep-1999 11:33

Something about the PHP build process is needed here; perhaps an example showing how to make your own "Hello, World" extension. Since that doesn't exist yet...


If you want to create an extension, you will need reasonably current versions of the tools m4, autoconf, libtool, and (I think) automake. All of these are available at .


Once these are installed, go into the 'ext' directory of your php install and run the 'ext_skel' script to create your extension directory with some skeleton contents. You will need to edit at least the config.m4 file, and of course add your own code. Other extensions are useful models, and the GNU documentation for autoconf is useful for understanding macros used in config.m4.


The final step required to insert your code into the PHP build process is to go to the php root directory and run the 'buildconf' script. You should now find references to your extension in the 'configure' script, and if you designed your config.m4 to make your extension conditional, 'configure' should have command-line switches for you.


After running 'configure', your extension should now be part of PHP's build process. (You may want to verify that php_config.h has properly set any 'HAVE_<your-extension-here>' macros properly defined.) If this all goes well, you should be ready to concentrate on the C code for your extension.

[email protected]
17-May-2000 06:08

I couldn't find a simple description of how to build an extension to PHP, so after I'd worked it out, I wrote some instructions. You can find them at




I hope someone finds them useful!

[email protected]
14-Mar-2001 07:48

PORTING CUSTOM C FUNCTION FROM PHP3 TO PHP4

And I mean just functions, not full-fledged php extension. I had a couple
of them, working with PHP3, and I have ported them in PHP4. Here's how.

1) Makefile
you should have CFLAGS something like

-I/path/to/php/php-4.0.4pl1/Zend
-I/path/to/php/php-4.0.4pl1
-I/path/to/php/php-4.0.4pl1/TSRM
-I/path/to/php/php-4.0.4pl1/main
-fPIC
-DCOMPILE_DL=1

Only the include paths changed from PHP3.

2) Interface with PHP
the php3_module_entry is now called zend_module_entry and has
the same structure. The get-module function from which you used to
return that value is not DLEXPORT, but ZEND_DLEXPORT. You
may want to use the ZEND_GET_MODULE macro.

For the function_entry, you may want to use the PHP_FE macros,
but I found the PHP_NAMED_FUNCTION implied less changes.
It goes as
PHP_NAMED_FUNCTION(arrayret); /* declaration */
and

/* in php3 was
DLEXPORT void arrayret(INTERNAL_FUNCTION_PARAMETERS) */
PHP_NAMED_FUNCTION(arrayret) /* definition */
{
pval **arg;
char buf[512];
int ok = 0, i = -1;

if (ZEND_NUM_ARGS() != 1 ||
zend_get_parameters_ex(1, &arg) != SUCCESS ||
(*arg)->type != IS_STRING ||
(*arg)->value.str.val == NULL)
{
WRONG_PARAM_COUNT;
}
...
You've seen that *arg becomes **arg. The ..._ex() function will take
the address of a pointer to pointer. ZEND_NUM_ARGS doesn't take
any parameter (used to be ht).

3) Includes

#include <php.h>
#include <zend_globals.h>

4) Insert indirection
One difficult point is the extra level of indirection that was introduced
for reference counting. If you don't use complex data types your C
function should now work. If you use, e.g., arrays, keep that level
of indirection in mind: don't store a pval into an array, store a pointer.

I had things as

if (array_init(return_value) == SUCCESS)
{
ok = 1;
for (i = 0; i < 100 && ok; ++i) /* insert 100 arrays in return value */
{
pval entry;
char buf[80];

if ((ok = array_init(&entry) == SUCCESS) != 0)
{
static char const entry_1[] = "one";
static char const entry_2[] = "two";

pval e1, e2;

e1.value.str.val = e2.value.str.val = NULL;
e1.type = e2.type = IS_STRING;

e1.value.str.len = sprintf(buf, "%3d/%010u", i, i);
e1.value.str.val = estrndup(buf, e1.value.str.len);
ok = e1.value.str.val != NULL &&
_php3_hash_update(entry.value.ht, (char*)entry_1,
sizeof entry_1, &e1, sizeof e1, NULL) == SUCCESS;

if (ok) /* continue assigning a second string, etc... */
...

This stuff compiles due to some compatibilty macro definitions, but
it doesn't work. The quickest way around is to insert an intermediate
function. To make the code above work in PHP4 i preceded it with
the following:

#undef _php3_hash_update
#define _php3_hash_update php4_hash_update_patch

static int php4_hash_update_patch(HashTable *ht,
char *arKey, uint nKeyLength,
void *pData, uint nDataSize, void **pDest)
{
zval *tmp;
int rtc;

if (nDataSize != sizeof(zval)) /* check it was a pval */
return FAILURE;

ALLOC_ZVAL(tmp); /* you need zend_globals.h for this */
*tmp = *(zval*)pData;
tmp->is_ref = 0;
tmp->refcount = 1;
if ((rtc = zend_hash_update(ht,
arKey, nKeyLength,
(void*)&tmp, sizeof(zval*), pDest)) == FAILURE)
{
FREE_ZVAL(tmp);
}
return rtc;
}

Similar patches can be done for _php3_hash_next_index_insert,
etcetera. You got the idea.

I hope this may save some time to an occasional code porter,
keep in mind I'm not a zend (sic) guru, I just crashed my head
quite hardly before realizing what was going wrong.

And

5) good luck!

[email protected]
26-Apr-2001 04:19

I recomended visit Zend API Documentation pages


[editor note: These docs also live in the PHP manual



Use those docs to Extend PHP 4]

[email protected]
21-Jun-2002 12:18

Just found out that functions in php need to neccessarily be in lower case! However, using a function like testMe doesn't throw any errors during compile time .. its just shows up as an undeclared function when called from a script. Instead use something like test_me & it works just fine.
add a note about notes
previousProtocole du d�buggeurAppeler des fonctions utilisateursnext
Last updated: Tue, 09 Jul 2002
show source | credits | stats | mirror sites
Copyright © 2001, 2002 The PHP Group
All rights reserved.
This mirror generously provided by:
Last updated: Fri Aug 30 04:14:06 2002 CEST