このセクションを読む前に 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;
}
}
これにより、リンクされたリスト全体のメモリが解放されます。
その間