ホームページ  >  記事  >  バックエンド開発  >  「PHP コア テクノロジーとベスト プラクティス」PHP 拡張機能の変数への値の代入

「PHP コア テクノロジーとベスト プラクティス」PHP 拡張機能の変数への値の代入

WBOY
WBOYオリジナル
2016-06-20 12:35:28949ブラウズ

このセクションを読む前に PHP の変数の構造を理解していない場合は、次のページに進んでください: PHP カーネルの変数

変数の機能は次のとおりです。データを保存します。PHP 変数では値だけでなく型も保存するため、変数に値を割り当てるだけでなく、変数の型を設定する必要もあります。

1) 長整数(integer)型変数: PHPカーネル内のすべての整数は長整数(long)であり、その値は前述のPHP変数zval構造体の共用体値に格納されます。 lval フィールド、対応する型は IS_LONG で、割り当てコードは次のとおりです:

zval *new_var;

MAKE_STD_ZVAL(new_var);

new_var->value。 lval = 12;

new_var->type = IS_LONG;

ただし、互換性を確保するには、ZVAL_LONG マクロ割り当てを使用するのが最善です:

zval *new_var;

MAKE_STD_ZVAL(new_var);

ZVAL_LONG(new_var,12);

上記の例は、コード

2) と同じ効果があります。倍精度 (浮動小数点) 型変数: 長整数代入との唯一の違いは、変数型が IS_DOUBLE、ZVAL_DOUBLE(new_var,12.56) であることです。3) 文字列型変数: 保存に加えて文字列の値。文字列も保存する必要があります。 文字列の長さ (strlen() などの関数で使用するために提供されます)。文字列の値は zval 構造体の値共用体の str 構造体の val フィールドに格納され、文字列の長さは str 構造体の len フィールドに格納され、さらに対応する型が IS_STRING に設定されます。文字列値を保存するために内部ブロックを使用すると、これらのメモリを自分で管理する必要がなくなり、ZEND エンジンのプロセスがより便利になることに注意してください。

zval *new_var;

char *str = "これは n 個の新しい文字列変数です";

MAKE_STD_ZVAL(new_var);

new_var->value.str.len = strlen(str);

new_var->value.str.val = estrdup(str); //estrdup は ZEND エンジンのメモリ管理関数です。

new_var->type = IS_STRING;

ZEND_STRING マクロを使用して値を割り当てます: ZVAL_STRING(new_var,str,1); ここの 3 番目のパラメーターは、文字列をコピーする必要があるかどうかを示します。 (ZEND エンジンのメモリ管理関数を使用) 1 に設定すると、これら 2 つのパラメータが指す文字列がコピーされます。0 に設定すると、val フィールドはこれら 2 つのパラメータが指す文字列を直接指します (可能)。参照割り当てとして理解されます)。

文字列の一部のみを取得したい場合、または代入する文字列の長さがすでにわかっている場合は、マクロ ZEND_STRINGL(zval, string, length, dedicated) を使用してパラメータの作業を完了できます。 length は指定された文字列の長さです。ZVAL_STRINGL マクロは ZVAL_STRING マクロより高速で、その定義は次のとおりです:

#define ZVAL_STRINGL(z,s,l,duplicate) {

char *_s = (s); int _l = l ;

(z)->value.str.len = _l; .val = (duplicate ? estrndup(_s,_l) : _s );

(z)->type =IS_STRING;

}

から見ることができます文字列 (len フィールド) の長さが length パラメーターに直接設定されるという定義。そのため、文字列の長さを計算するために strlen() を使用しなくなりました。空の文字列を作成する場合は、その長さを 0 に設定します。文字列の値として empty_string を使用します

new_var-> ;value.str.len = 0;

new_var->value.str.val = empty_string;

new_var->type = IS_STRING; または、ZVAL_EMPTY_STRING マクロを使用して完了します:

ZVAL_EMPTY_STRING(new_string) //ここには欠落しているパラメーターがないため、ZVAL_EMPTY_STRING(new_var,new_string);?

4) ブール型変数: ブール型の割り当ては整数型の割り当てと似ていますが、異なる点は、データ型フィールドが IS_BOOL に設定され、lval フィールドの値は次のとおりです。 ZVAL_BOOL マクロ コードは次のとおりです: ZVAL_BOOL(new_var,1);

5) 配列型変数: PHP では配列が重要な役割を果たします。カーネルでは、配列はハッシュ テーブル (HashTable) を使用して保存されるため、最初に HashTable を作成し、それを zval の ht フィールドに保存する必要があります。 Zend エンジンは、この作業を完了するための単純なインターフェイス array_init() を提供します。コードは次のとおりです:

zval *new_var;

MAKE_STD_ZVAL (new_var);

array_init(new_array);

上記のコードは、

と同等であり、空の配列を作成した後、それに要素を追加できます。 API はすべて利用可能です。以下にリストします (成功した場合は SUCCESS が返され、失敗した場合は FAILURE が返されます):

連想配列の API:

add_assoc_long(zval *array, char *key,long n); to $array["key"]=10;

add_assoc_unset(zval *array,char *key); //$array["key"] = NULL ;

add_assoc_bool(zval * array,char *key,int b);

add_assoc_resource(zval *array,char *key,int r);

add_assoc_double(zval *array,char *key,double d);

add_assoc_string(zval *array,char *key,char *str,int重複); //$array["key"] = "string";

add_assoc_stringl(zval *array,char *key,char *str,uinit length,int duplicate); //指定された長さの文字列を追加します

add_assoc_zval(zval *array,char *key,zval * value); // zval 構造体を追加します。これは、$array["key"] = $value;

と同等の、別の配列、オブジェクト、ストリームなどのデータを追加するときに役立ちます。配列のインデックス付け用の API: Index配列は連想配列と非常に似ています。違いは添え字が文字列であるか整数であるかにあります。したがって、上記のプロトタイプのすべての char *key をユニット IDx に置き換えることがインデックス配列の API であり、これは再度リストされません。

上記の API は単なる抽象的な HashTable API 関数であり、zend_hash_update() 関数を使用して配列 sk に要素を追加するなど、HashTable API 関数を直接使用して操作することもできます。 API を使用して要素を配列に追加する例:

zval array,element

char *key = "検索用のキー";

char *value = "要素の値" ;

MAKE_STD_ZVAL(配列);

MAKE_STD_ZVAL(要素);

array_init(配列);

ZVAL_STRING(要素,値,1 );

add_assoc_zval(array,key,element);

6) オブジェクト型変数: 変数によってオブジェクト型に割り当てられる値を説明する前に、次のことを行う必要があります。まず、PHP によるオブジェクトと配列の使用法を理解します。 関係: オブジェクトは配列に変換できます (オブジェクトの機能が失われるため、このプロセスは元に戻すことはできません)。また、オブジェクトと配列のプロパティは相互に変換可能です。オブジェクトの関数などは HashTable に保存する必要がありますか?この問題は、後で PHP カーネルの関数を理解したときに解決されます。

オブジェクトを作成する API コードは次のとおりです:

zval *new_object;

MAKE_STD_ZVAL(new_object);

if(object_init(new_object) !=SUCCESS ) {

RETURN_NULL();

}

オブジェクトにプロパティを追加するための Zend エンジンの API は次のとおりです:

add_property_long(zval *object,char

key,long l);

object,char *key);

add_property_bool(zval *object,char *key,int b);

add_property_resource (zval *object,char *key, long r);

add_property_double(zval *object,char *key,double d);

add_property_string(zval *object,char *key,char *str,int重複) ;

add_property_stringl(zval *object,char *key,char *str,uint length,int重複);

add_property_zval(zval *object,char *key, zval *container);

たとえば、「name」という名前の属性を追加し、次のように文字列を入力します。

if( object_init(new_object)!=SUCCESS) {

RETURN_NULL();

}

add_property_string(new_object,"name","James ",1);

7) リソース タイプ変数: リソース タイプ変数の作成は、他のタイプの変数を作成するよりも少し面倒です。厳密に言えば、リソースはデータ タイプではありません。これは、任意のデータ型 (つまり、C 言語のポインターのような) を維持できる抽象化です。すべてのリソースは Zend 内部リソース リストに保存されます。リスト内の各リソースには実際のデータへのポインタが含まれています。PHP カーネルについて十分な知識がある場合は、これらのリソースに直接アクセスできますが、これは互換性とセキュリティのためです。 Zend エンジンが提供する API を使用してアクセスすることをお勧めします。

リソースがすべての参照を失うと、対応するデストラクターがトリガーされます。このデストラクターはリソース自体によって提供されます。その理由は、zend エンジンがリソースの実際のデータを管理できないためです。メモリ リークが発生した場合は、メモリを解放するためにデストラクタを提供する必要があります。

データベース接続とファイル演算子は PHP リソース タイプであり、カスタマイズされたデータ構造やその他のタイプのデータもリソース タイプとして保存できます。

zend_register_list_destructors_ex() 関数は、リソース変数のデストラクターを登録するために使用できます。この関数は、リソースへのハンドルを返します。リソース ハンドルの機能は、リソースをリソースのデストラクターに関連付けることです。以下は、Zend_register_list_destructors_ex()関数定義:

zend_api int_zend_register_list_destructors_ex(rsrc_dtor_func_t ld、rsrc_dtor_func_t pld、chr *int module_numper \普通のuctorリソース、

pld: 永続リソースのデストラクター、

type_name: リソースの名前を指定します。ユーザーは var_dump($resource) を呼び出します。 )、リソースの名前を取得できます。

module_number: モジュールの PHP_MINIT_FUNCTION 関数で自動的に定義されるため、無視できます。

ld と pld の少なくとも 1 つを指定する必要があり、もう一方のデストラクターは単純に NULL に設定できます。

リソース デストラクターのプロトタイプは次のように定義する必要があります: void resource_destruction_handler(zend_rsrc_entry *rsrc) TSRMLS_DC ; 通常、ptr フィールドが指すメモリはデストラクターで解放されます

int type;

int refcount;

} zend_rsrc_list_entry;

たとえば、リンク リスト データ構造を次のように定義します。

typedef struct _ListNode {

struct _ListNode *next;

void *data ;

} ListNode;

次に、リソース変数はこのリンクされたリストの先頭ポインターを保存します。デストラクターは次のように記述できます。

void list_destroy_handler( zend_rsrc_list_entry

rsrc TSRMLS_DC ) {

ListNode current,next;

)rsrc->ptr; ここで、ポインタ型変換はリソースを変換します。 ptr によって ListNode リンクされたリスト リソースに指定されますか?

while(current) {

next = current->next;

free(current);

current = next;

}

}

これにより、リンクされたリスト全体のメモリが解放されます。

その間

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。