Heim php教程 php手册 php的扩展和嵌入--php内部变量

php的扩展和嵌入--php内部变量

Jun 13, 2016 am 10:19 AM
内部 嵌入 扩展

之前对于php的内部生命周期和Zend引擎的线程安全机制做了一个介绍,这里这篇文章则是主要介绍php的内部变量是如何实现的。

了解了这些实现的方法之后,对于写php,尤其是进行php扩展开发感觉相当有帮助。


php是一种类型比较松散的语言,与C相比不需要在使用变量前给出类型,直接用就可以。为了实现这一点,php必须在数据类型的定义上做一些工作。

数据类型:

最基本的类型被称为是zval或者说Zend Value,定义在Zend/zend.h头文件中。 typedef struct _zval_struct {
zvalue_value value;
zend_uint refcount;
zend_uchar type;
zend_uchar is_ref;
} zval; 其中zvalue_value按照如下定义: typedef union _zvalue_value {
long lval;
double dval;
struct {
char *val;
int len;
} str;
HashTable *ht;
zend_object_value obj;
} zvalue_value; 这个是一个union,使用union的时候两种可能,一种是所有的变量共享一片内存空间,一种是要对其中的类型进行n选1的时候。
Zend定义了8种基本的数据类型,这八种基本上在别的语言中也都见过,所以只对比较特殊的类型进行说明: IS_NULL:non-valueIS_BOOL:IS_LONGIS_DOUBLEIS_STRING:分配的空间需要是长度+1IS_ARRAY: php的数组其实是hashtable,其中包括label和dataIS_OBJECT:在数组的基础上加上了 方法、访问修改符、有域的常量以及特殊的事件处理器IS_RESOURCE:比如文件的句柄或是mysql的句柄这些存储在zval的type中,并且与zvalue_value有着分别的对应关系 注意下面有两个类型判断函数的对比:
void describe_zval(zval *foo)
{
    if (foo->type == IS_NULL) {
        php_printf("The variable is NULL");
    } else {
        php_printf("The variable is of type %d", foo->type);
    }
}
Nach dem Login kopieren
void describe_zval(zval *foo)
{
    if (Z_TYPE_P(foo) == IS_NULL) {
        php_printf("The variable is NULL");
    } else {
        php_printf("The variable is of type %d",
                            Z_TYPE_P(foo));
    }
}
Nach dem Login kopieren

第一段代码中采用的是c的写法,第二段代码是带有php特色的写法。 注意到Zend头文件中提供了很多对zval处理的宏,最好用它们,这里就是用了Z_TYPE_P(foo)。同样还有Z_TYPE()和Z_TYPE_PP()分别对应zval和zval** php_printf()则是在printf的基础上做了些针对SAPI和php输出机制的优化。


数据值

通过一些宏可以获取不同类型的zval的值: BVAL(): BooleanLVAL(): longDVAL(): double 这个函数针对三种不同的zval类型,分别利用Z_TYPE进行了类型判断。然后利用相应的值提取的宏进行取值。
void display_values(zval boolzv, zval *longpzv,
               zval **doubleppzv)
{
    if (Z_TYPE(boolzv) == IS_BOOL) {
        php_printf("The value of the boolean is: %s\n",
            Z_BVAL(boolzv) ? "true" : "false");
    }
    if (Z_TYPE_P(longpzv) == IS_LONG) {
        php_printf("The value of the long is: %ld\n",
            Z_LVAL_P(longpzv));
    }
    if (Z_TYPE_PP(doubleppzv) == IS_DOUBLE) {
        php_printf("The value of the double is: %f\n",
            Z_DVAL_PP(doubleppzv));
    }
}
Nach dem Login kopieren

对于string的处理则要稍微特殊一些:需要两个宏Z_STRVAZ_STRLEN分别读取值和长度,这个从string类型的定义中也可以看到,它是由字符和长度组成的。
void display_string(zval *zstr)
{
    if (Z_TYPE_P(zstr) != IS_STRING) {
        php_printf("The wrong datatype was passed!\n");
        return;
    }
    PHPWRITE(Z_STRVAL_P(zstr), Z_STRLEN_P(zstr));
}
Nach dem Login kopieren

对数组的访问使用的是ARRVAL系列:Z_ARRVAL(zv), Z_ARRVAL_P(pzv), Z_ARRVAL_PP(ppzv). 有一些版本的php源码中HASH_OF()等同于Z_ARRVAL_P,但是这个宏已经渐渐的用的少了.
对于Object: OBJ_HANDLE 返回对象句柄标识OBJ_HT 句柄表OBJCE 类定义OBJPROP 属性哈希表OBJ_HANDLER 在OBJ_HT中操作特定处理方法 对于资源Resource就直接用宏RESVAL

数据创建:

想要创造一个变量并分配空间的malloc(sizeof(zval))在php这里并不可行。应该使用MAKE_STD_ZVAL(pzv), 它对空间的分配进行了优化,并且会自动的初始化refCount(表示这个变量被引用的次数)和is_ref(是否是强制引用)这两个性质。注意它的输入是一个指针.
ALLOC_INIT_ZVAL()也可以进行初始化,不同之处在于把zval*的值设为了NULL.
在设置不同类型的值的时候有很多形式,左边是比较简略的形式,右侧则是展开的形式: ZVAL_NULL(pvz); Z_TYPE_P(pzv) = IS_NULL;
ZVAL_BOOL(pzv, b); Z_TYPE_P(pzv) = IS_BOOL;
Z_BVAL_P(pzv) = b ? 1 : 0;
ZVAL_TRUE(pzv); ZVAL_BOOL(pzv, 1);
ZVAL_FALSE(pzv); ZVAL_BOOL(pzv, 0);
ZVAL_LONG(pzv, l); Z_TYPE_P(pzv) = IS_LONG;
Z_LVAL_P(pzv) = l;
ZVAL_DOUBLE(pzv, d); Z_TYPE_P(pzv) = IS_DOUBLE;
Z_DVAL_P(pzv) = d;
对于字符串的处理要特殊一些,提供了一个单独的参数dup. 这个参数决定了是否创建一个字符串的副本.举个例子 zval * pzva; ZVAL_STRING(pzval,"hello world",1); 由于“hello_world”是一个常量字符串,直接对它进行操作显然不合适,所以把dup设为1的话,会自动的给它创建一个副本,然后再赋给pzval. 这使得整个过程更加简洁。

ZVAL_STRINGL(pzv,str,len,dup); Z_TYPE_P(pzv) = IS_STRING;
Z_STRLEN_P(pzv) = len;
if (dup) {
Z_STRVAL_P(pzv) =
estrndup(str, len + 1);
} else {
Z_STRVAL_P(pzv) = str;
}
ZVAL_STRING(pzv, str, dup); ZVAL _STRINGL(pzv, str,
strlen(str), dup); 注意dup如果设为1的话就是申请新的空间并且拷贝内容,而不是一个shaddow copy。 ZVAL_RESOURCE(pzv, res); Z_TYPE_P(pzv) = IS_RESOURCE;
Z_RESVAL_P(pzv) = res;


数据的存储

数据的存储都在符号表中。 symbol table,每当创建一个新的变量的时候,Zend都保存这个值到这个内部的数组中去。 符号表在RINIT之前创建,在RSHUTDOWN之后销毁。
当用户空间的函数或对象方法被调用的时候,会创建一个新的符号表,生命与函数执行时间相同。 在Zend/zend_gblobals.h中定义了两个元素:
struct _zend_executor_globals {
    ...
    HashTable symbol_table;
    HashTable *active_symbol_table;
    ...
};
Nach dem Login kopieren

通过EG(symbol_table) 的方式可以访问符号表。感觉跟$GLOBALS似的。 注意到EG(symbol_table)这个宏返回的不是指针,必须加上&。 下面的这个对比非常的有趣: In PHP:
<?php $foo = 'bar'; ?>
Nach dem Login kopieren
针对这段php的代码,C中一共做了如下这些事:
In C:
{
    zval *fooval;
    MAKE_STD_ZVAL(fooval); //首先分配空间,设置变量
    ZVAL_STRING(fooval, "bar", 1); //然后赋值,创建一个copy,你不能直接操作常字符串
    ZEND_SET_SYMBOL(EG(active_symbol_table), "foo", fooval); // 在符号表中注册,foo是一个label
}
Nach dem Login kopieren
所谓active_symbol_table指的是程序执行当前的符号表,在进入一个函数之后,会有它自己对应的符号表,就类似于C中针对一个函数自己的栈空间。而当退出了函数之后,它的符号表会被销毁,这时候又回到了下面这个状态: EG(active_symbol_table) == &EG(symbol_table), 这个时候并没有进入函数。

数据的获取: 在获取数据的时候,比较多的是使用zend_hash_find()函数:

{
    zval **fooval;
    if (zend_hash_find(EG(active_symbol_table),
                       "foo", sizeof("foo"),
                       (void**)&fooval) == SUCCESS) {
        php_printf("Got the value of $foo!");
    } else {
        php_printf("$foo is not defined.");
    }
}
Nach dem Login kopieren
这个函数首先查找符号表,找到名字为“foo”的变量,然后返回到fooval中。下面着重解释两个问题:

为什么要声明一个zval ** fooval 然后还要通过&fooval并且转换为(void **)的形式?为什么要用sizeof("foo") 对第一个问题,要考虑到我们寻找的目标是一个zval*,所以要把它看作一个整体。利用这种写法可以避免编译告警。 第二个问题,使用sizeof(label)主要是为了表示字符串常量label的尾部,这里使用4也是可以的,但是通用性不够。

数据转换: 仅仅是说一下有这个功能,比如convert_to_string(zval *value)可以把zval转换为字符串。


以上就是php内部变量的一些介绍,为了能够区分不同的类型、设置获取变量值以及在符号表中增加和查找变量,这些知识必不可少。




Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn

Heiße KI -Werkzeuge

Undresser.AI Undress

Undresser.AI Undress

KI-gestützte App zum Erstellen realistischer Aktfotos

AI Clothes Remover

AI Clothes Remover

Online-KI-Tool zum Entfernen von Kleidung aus Fotos.

Undress AI Tool

Undress AI Tool

Ausziehbilder kostenlos

Clothoff.io

Clothoff.io

KI-Kleiderentferner

AI Hentai Generator

AI Hentai Generator

Erstellen Sie kostenlos Ai Hentai.

Heißer Artikel

R.E.P.O. Energiekristalle erklärten und was sie tun (gelber Kristall)
3 Wochen vor By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Beste grafische Einstellungen
3 Wochen vor By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. So reparieren Sie Audio, wenn Sie niemanden hören können
3 Wochen vor By 尊渡假赌尊渡假赌尊渡假赌

Heiße Werkzeuge

Notepad++7.3.1

Notepad++7.3.1

Einfach zu bedienender und kostenloser Code-Editor

SublimeText3 chinesische Version

SublimeText3 chinesische Version

Chinesische Version, sehr einfach zu bedienen

Senden Sie Studio 13.0.1

Senden Sie Studio 13.0.1

Leistungsstarke integrierte PHP-Entwicklungsumgebung

Dreamweaver CS6

Dreamweaver CS6

Visuelle Webentwicklungstools

SublimeText3 Mac-Version

SublimeText3 Mac-Version

Codebearbeitungssoftware auf Gottesniveau (SublimeText3)

Wie verwende ich die SNMP-Erweiterung von PHP? Wie verwende ich die SNMP-Erweiterung von PHP? Jun 02, 2023 am 10:22 AM

Die SNMP-Erweiterung für PHP ist eine Erweiterung, die es PHP ermöglicht, über das SNMP-Protokoll mit Netzwerkgeräten zu kommunizieren. Mit dieser Erweiterung können Sie auf einfache Weise die Konfigurationsinformationen von Netzwerkgeräten abrufen und ändern, z. B. CPU, Speicher, Netzwerkschnittstelle und andere Informationen von Routern, Switches usw. Sie können auch Steuervorgänge durchführen, z. B. das Umschalten von Geräteports. In diesem Artikel werden die Grundkenntnisse des SNMP-Protokolls, die Installation der SNMP-Erweiterung von PHP und die Verwendung der SNMP-Erweiterung in PHP zur Überwachung und Steuerung von Netzwerkgeräten vorgestellt. 1. SN

PHP mit HTML kombinieren: drei Techniken zum Einbetten von Code PHP mit HTML kombinieren: drei Techniken zum Einbetten von Code Mar 06, 2024 am 08:09 AM

Die Kombination von PHP und HTML ist eine gängige Technologie in der Webentwicklung. PHP kann dynamische Inhalte in HTML-Dateien einbetten und Hilfsfunktionen implementieren, was die Interaktivität und Anpassbarkeit der Website erheblich verbessert. In diesem Artikel werden drei Techniken zum Einbetten von Code vorgestellt und spezifische Codebeispiele als Referenz bereitgestellt. 1. Verwenden Sie PHP-Tags zum Einbetten von Code. Die häufigste Methode ist die Verwendung von PHP-Tags (), um PHP-Code in HTML-Dateien einzubetten, um dynamische Inhalte anzuzeigen. Sie können beispielsweise PHP verwenden

Von Anfang bis Ende: So verwenden Sie die PHP-Erweiterung cURL, um HTTP-Anfragen zu stellen Von Anfang bis Ende: So verwenden Sie die PHP-Erweiterung cURL, um HTTP-Anfragen zu stellen Jul 29, 2023 pm 05:07 PM

Von Anfang bis Ende: So verwenden Sie die PHP-Erweiterung cURL für HTTP-Anfragen. Einführung: Bei der Webentwicklung ist es häufig erforderlich, mit APIs von Drittanbietern oder anderen Remote-Servern zu kommunizieren. Die Verwendung von cURL zum Senden von HTTP-Anfragen ist eine gängige und leistungsstarke Methode. In diesem Artikel wird erläutert, wie Sie mit PHP cURL erweitern, um HTTP-Anfragen auszuführen, und einige praktische Codebeispiele bereitstellen. 1. Vorbereitung Stellen Sie zunächst sicher, dass PHP die cURL-Erweiterung installiert hat. Zur Überprüfung können Sie php-m|grepcurl in der Befehlszeile ausführen

Erweiterungen und Drittanbietermodule für PHP-Funktionen Erweiterungen und Drittanbietermodule für PHP-Funktionen Apr 13, 2024 pm 02:12 PM

Um die Funktionalität der PHP-Funktion zu erweitern, können Sie Erweiterungen und Module von Drittanbietern verwenden. Erweiterungen stellen zusätzliche Funktionen und Klassen bereit, die über den pecl-Paketmanager installiert und aktiviert werden können. Module von Drittanbietern bieten spezifische Funktionen und können über den Composer-Paketmanager installiert werden. Zu den praktischen Beispielen gehören die Verwendung von Erweiterungen zum Parsen komplexer JSON-Daten und die Verwendung von Modulen zur Datenvalidierung.

Wie installiere ich die MBstring-Erweiterung unter CENTOS7? Wie installiere ich die MBstring-Erweiterung unter CENTOS7? Jan 06, 2024 pm 09:59 PM

1.UncaughtError:Calltoundefinedfunctionmb_strlen(); Wenn der obige Fehler auftritt, bedeutet dies, dass wir die mbstring-Erweiterung nicht installiert haben. 2. Geben Sie das PHP-Installationsverzeichnis cd/temp001/php-7.1.0/ext/mbstring ein. 3. Starten Sie phpize( /usr/local/bin /phpize oder /usr/local/php7-abel001/bin/phpize) Befehl zum Installieren der PHP-Erweiterung 4../configure--with-php-config=/usr/local/php7-abel

So verwenden Sie die Aurora Push-Erweiterung, um die Push-Funktion für Stapelnachrichten in PHP-Anwendungen zu implementieren So verwenden Sie die Aurora Push-Erweiterung, um die Push-Funktion für Stapelnachrichten in PHP-Anwendungen zu implementieren Jul 25, 2023 pm 08:07 PM

So verwenden Sie die Aurora Push-Erweiterung zum Implementieren der Batch-Nachrichten-Push-Funktion in PHP-Anwendungen. Bei der Entwicklung mobiler Anwendungen ist Message Push eine sehr wichtige Funktion. Jiguang Push ist ein häufig verwendeter Nachrichten-Push-Dienst, der umfangreiche Funktionen und Schnittstellen bietet. In diesem Artikel wird erläutert, wie Sie die Aurora Push-Erweiterung verwenden, um die Push-Funktionalität für Batch-Nachrichten in PHP-Anwendungen zu implementieren. Schritt 1: Registrieren Sie ein Jiguang Push-Konto und erhalten Sie einen API-Schlüssel. Zuerst müssen wir uns auf der offiziellen Website von Jiguang Push registrieren (https://www.jiguang.cn/push).

Wie verwende ich die ZipArchive-Erweiterung von PHP? Wie verwende ich die ZipArchive-Erweiterung von PHP? Jun 02, 2023 am 08:13 AM

PHP ist eine beliebte serverseitige Sprache, mit der Webanwendungen entwickelt und Dateien verarbeitet werden können. Die ZipArchive-Erweiterung für PHP ist ein leistungsstarkes Tool zum Bearbeiten von Zip-Dateien in PHP. In diesem Artikel erfahren Sie, wie Sie die ZipArchive-Erweiterung von PHP zum Erstellen, Lesen und Ändern von Zip-Dateien verwenden. 1. Installieren Sie die ZipArchive-Erweiterung. Bevor Sie die ZipArchive-Erweiterung verwenden, müssen Sie sicherstellen, dass die Erweiterung installiert wurde. Die Installationsmethode ist wie folgt: 1. Installieren

Wie verwende ich die POSIX-Erweiterung von PHP? Wie verwende ich die POSIX-Erweiterung von PHP? Jun 03, 2023 am 08:01 AM

POSIX-Erweiterungen für PHP sind eine Reihe von Funktionen und Konstanten, die es PHP ermöglichen, mit POSIX-kompatiblen Betriebssystemen zu interagieren. POSIX (PortableOperatingSystemInterface) ist eine Reihe von Betriebssystemschnittstellenstandards, die es Softwareentwicklern ermöglichen sollen, Anwendungen zu schreiben, die auf verschiedenen UNIX- oder UNIX-ähnlichen Betriebssystemen ausgeführt werden können. In diesem Artikel wird die Verwendung von POSIX-Erweiterungen für PHP, einschließlich Installation und Verwendung, vorgestellt. 1. Installieren Sie die POSIX-Erweiterung von PHP in

See all articles