Problem : Kendi
hazirladiginiz C fonksiyonlarini, PHP betikleri icinden kullanmak
istiyorsunuz.
Cozum : Ornek bir "C Programi" hazirlayip, PHP icerisine yerlestirelim.Ardindan
PHP'yi bu yeni ekledigimiz fonksiyon ile derleyip sisteme
tekrar yukleyelim...
PHP_FUNCTION(sample_function)
{
char *ret = NULL,
*fmtstr;
zval **arg1, **arg2, **arg3;
if (ZEND_NUM_ARGS() != 3 ||
zend_get_parameters_ex (3, &arg1, &arg2, &arg3)
== FAILURE) {
WRONG_PARAM_COUNT;
}
/* arg1 is an int */
convert_to_long_ex (arg1);
/* arg2 is a double */
convert_to_double_ex (arg2);
/* arg3 is a string */
convert_to_string_ex (arg3);
fmtstr = "arg1 is %d, arg2 is %f and arg3 is %s, arg3 has
a length of %d";
/* Not the best allocation for integer values
* but sufficient for the needs of this simple program.
*/
ret = emalloc(strlen(fmtstr) + 10 + 20 + Z_STRLEN_PP(arg3));
sprintf(ret, fmtstr, Z_LVAL_PP(arg1), Z_DVAL_PP(arg2),Z_STRVAL_PP(arg3),
Z_STRLEN_PP(arg3));
RETURN_STRING(ret, 0);
}
Tartisma :
Bu ornek fonksyion PHP betikleri icerisinden asagidaki sekilde
cagrilabilir :
echo sample_function (23, 23.34003, "Hello World");
Bunun sonucunda asagidaki gibi bir ifade donecektir :
arg1 is 23, arg2 is 23.34003 and arg3 is Hello World, arg3
has a length of 11
Program nasil calisiyor?
Satir 1 - PHP foksiyonu olarak deklare ediyoruz.
Satir 4 - arg1,arg2 ve arg3'u zval degiskenleri olarak deklare
ediyoruz.zval asagidaki yapiya sahiptir :
typedef _zval_struct zval;
/* Notice that is a union, meaning only one of the entries
exists at a single time */
typedef union _zval_value {
long lval; /*the long value */
double dval; /*The double value */
struct {
char *val; /* The value of the string */
int len; /* The length of the string */
} str;
char chval;
HashTable *ht; /* If it is an array */
struct {
zend_class_entry *ce;
HashTable *properties;
} obj; /* Object properties */
} zvalue_value;
/* The actual zval struct itself, aliased by the typedef
above */
struct _zval_struct {
zvalue_value value; /* Value of argument */
zend_uchar type; /* Type of the argument */
zend_uchar is_ref; /* Whether or not the argument is a reference
*/
zend_ushort refcount; /* The reference count on the argument
*/
};
Satir 5 - Fonksiyonumuza 3 tane argumentin gecirildigine emin
oluyoruz.ZEND_NUM_ARGS () fonksiyona gecirilen argument sayisini
dondurur.
Satir 6 - zend_get_parameters_ex () fonksiyonu ile yazdigimiz
fonksiyona gecirilen degiskenlerin icindeki degerler "zval"
degerleri olarak deklare ediliyor.
Satir 7 - Bu islem basarisiz olursa, hatayi rapor et.
Satir 11 - arg1'i long'a cevir.
Satir 13 - arg2'yi double'a cevir.
Satir 15 - arg3'u string'e cevir.
Satir 18 - String formatini olustur.
Satir 19 - Hafizaya yerlestir.
Satir 20 - Donecek degeri olustur.
Satir 21 - Donecek degeri dondur.
Ek Aciklama :
Bilmeyenler icin kisa bir tekrar yapalim.Integer,Double ve
String ne demektir?
1.Integer (Ondalik kisimi olmayan sayi veri tipi)
2.Double (Tam ve ondalik olmak uzere iki kisimdan olusan
sayi veri tipi)
3.String ( Genel olarak bilinen karekter (yazi) veri formati.PHP
icerisindeki betiklerde mutlaka " veya ' icerisine yazilmalidir.)
Eger PHP'nin kaynak kodunu incelerseniz gozunuze asagidaki
gibi satirlar carpacaktir :
pval **argument;
aslinda :
zval **argument;
olmasi gereklidir.PHP 3 icerisinde butun argumentler zval'ler
yerine pval'ler seklindeydi.PHP 3 kaynak kodunu PHP 4 kaynak
koduna aktarabilmek icin , zval ve pval'leri ayni sey yapmak
gerekli idi.Bu olay basitce "typedef" ile saglanmistir.
Ek Bilgi :
Bir degiskenin icine, fonksiyona gecirilen argument sayisini
gidip getirmesini soylemek icin :
PHP_FUNCTION(birfonksiyon)
{
zval **arg1, **arg2;
int argcount = ZEND_NUM_ARGS();
if (argcount > 2 || argcount < 0 || zend_get_parameters_ex(argcount,&arg1,
&arg2) == FAILURE) {
WRONG_PARAM_COUNT;
}
if (argcount > 0) {
convert_to_long_ex(arg1);
/* php_printf prints out to STDOUT */
php_printf("%dn", Z_LVAL_PP(arg1));
}
if (argcount > 1) {
convert_to_string_ex(arg2);
php_printf("%sn", Z_STRVAL_PP(arg2));
}
php_printf("Above are %d printed out arguments", argcount);
}
zend_get_parameters_ex () fonksyionu, yanlizca ilk argument
ile verilen sayi kadar argumentle eslesir.Bu sebeple yanlizca
sizin istediginiz sayidaki degisken fonksiyona argument olarak
gecer.
PHP'ye bu yeni fonksiyonu eklemek :
1.Fonksiyonun kaynak kodunu dogru dosyanin icine yerlestirin;
sample_function () fonksiyonu icin basic_functions.c
PHP dosyasinin icine yerlestirme yapabiliriz.
2.Bu dosyanin icinde yukarilarda bir yerde asagidaki gibi
satirlarin gectigi yeri bulunuz. (Eger bu fonksiyonu ext/standard
icine yerlestiriyorsaniz, basic_functions.c dosyasinin icinde
en yukarilarda bir yere bakmalisiniz.)
function_entry MODULENAME_functions[] = {
PHP_FE(somefunction, NULL)
...
}
Kendi yazdiginiz fonksiyon icin asagidaki gibi bir satir ekleyebilirsiniz
:
PHP_FE(sample_function, NULL)
Simdi asagidaki gibi bir goruntu olmali :
function_entry MODULENAME_functions[] = {
PHP_FE(somefunction, NULL)
PHP_FE(sample_function, NULL)
...
}
3.Bu dosya icin var olan "header" dosyasina gidin."header"
dosyalari genelde php_MODULENAME.h olarak isimlendirilen dosyalardir.
Bu dosyanin icinde bir cok deklarasyon goreceksiniz :
PHP_FUNCTION(somefunction);
Siz asagidaki gibi bir satiri eklemelisiniz :
PHP_FUNCTION(sample_function);
4.PHP'yi tekrar derleyin ve sisteme yukleyin.Betikleriniz
isinden artik yeni fonksiyonunuzu cagirebilirsiniz.
Kaynak : ISBN 0-672-31924-1
Serkan Hadi Ceylani
serkan@turk-php.com
Kurko (08/10/01)
http://zend.com/zend/api.php burdaki url de
daha genis acıklama var. Anladıgım kadarı ile sadece programı
compile etmek yeterli, program extension olarak yukleniyor.
<?
dl("test.dll");
?>
Gibi.
|