php扩展与嵌入--php扩展的参数
之前的文章中,函数在接收的参数和返回的类型上都比较简单,但是往往实际中所遇到的都更加复杂一些。这篇文章主要说一下如何在php扩展开发中接收来自于用户空间的参数,并且对这些参数的类型、个数等信息进行相应的检查。
1. 使用zend_parse_parameters()进行自动的类型转换
在php的扩展中,最容易的得到输入参数的方法就是使用zend_parse_parameters()函数。
对这个函数的调用的第一个参数总是:ZEND_NUM_ARGS() TSRMLS_CC. 这个参数返回一个int型的输入参数的数目。第二个参数是format参数,是由字符串类型组成,分别对应着不同的Zend Engine支持的类型。
下图中给出了format参数可能具有的类型:
而接下来的参数取决于之前所请求的类型。对于比较简单的类型来说,这个参数一般都是取引用的基元,如下例所示:
PHP_FUNCTION(sample_getlong) { long foo; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &foo) == FAILURE) { RETURN_NULL(); } php_printf("The integer value of the parameter you " "passed is: %ld\n", foo); RETURN_TRUE; }
注意到对于复杂的类型采用的是简单的zval*类型。这跟返回复杂类型的时候没有RETURN_*的道理是一样的。ZPP所做的事情是保证所接收到的zval*是正确的类型。如果必要的话,它也会执行隐式的转换,比如把数组转成stdClass对象。
对于s类型来说,它比较特殊,一个char*一个int,这个还是主要因为php里面字符串的特殊结构:
function sample_hello_world($name) { echo "Hello $name!\n"; }
PHP_FUNCTION(sample_hello_world) { char *name; int name_len; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name, &name_len) == FAILURE) { RETURN_NULL(); } php_printf("Hello "); PHPWRITE(name, name_len); php_printf("!\n"); }
如果有多个参数的话,那么zend_parse_parameters会从左到右去提取这些参数:
function sample_hello_world($name, $greeting) { echo "Hello $greeting $name!\n"; } sample_hello_world('John Smith', 'Mr.');
Or:
PHP_FUNCTION(sample_hello_world) { char *name; int name_len; char *greeting; int greeting_len; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &name, &name_len, &greeting, &greeting_len) == FAILURE) { RETURN_NULL(); } php_printf("Hello "); PHPWRITE(greeting, greeting_len); php_printf(" "); PHPWRITE(name, name_len); php_printf("!\n"); }
除了类型标识符之外,还有三个元字符来修改参数被处理的方式: | :如果看到它了,说明前面的参数都是必须的,后面的参数都是可选的! :如果接收了一个php语言中的null变量,则直接转成C语言里的NULL,而不是封装成IS_NULL类型的zval
/ :如果传递过来的变量与别的变量共用一个zval,而且不是真引用,那就要强制分离,新zval的is_ref__gc = 0,refcount__gc = 1 可选的参数: php中可以给参数提供默认值:
function sample_hello_world($name, $greeting='Mr./Ms.') { echo "Hello $greeting $name!\n"; }
sample_hello_world('Ginger Rogers','Ms.'); sample_hello_world('Fred Astaire');
在C的解释中,有类似的实现方式:
PHP_FUNCTION(sample_hello_world) { char *name; int name_len; char *greeting = "Mr./Mrs."; int greeting_len = sizeof("Mr./Mrs.") - 1;//给定默认值,找出默认的长度 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s", &name, &name_len, &greeting, &greeting_len) == FAILURE) {//特殊的元字符|立刻就用上了 RETURN_NULL(); } php_printf("Hello "); PHPWRITE(greeting, greeting_len); php_printf(" "); PHPWRITE(name, name_len); php_printf("!\n"); }
对于可选参数来说,除非指定一般是不会有值的,所以提供默认参数很重要。大部分的情况下是NULL/0
IS_NULL VS NULL:
每一个zval的类型,即使是最简单的IS_NULL类型,都占据一定的内存空间,同时也需要时间去申请和释放它们。所以很多时候没有必要使用这个类型,下面两段代码里面给出了对比:
PHP_FUNCTION(sample_arg_fullnull) { zval *val; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &val) == FAILURE) { RETURN_NULL(); } if (Z_TYPE_P(val) == IS_NULL) {//使用zval检查为空的方式 val = php_sample_make_defaultval(TSRMLS_C); } ... PHP_FUNCTION(sample_arg_nullok) { zval *val; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z!", &val) == FAILURE) { RETURN_NULL(); } if (!val) {// c语言风格的检查为空的方式 val = php_sample_make_defaultval(TSRMLS_C); } ...
Forced Seperation强制分离:
当一个变量传入函数的时候,不管是不是用传引用的方式,refcount总是至少为2.一个是本身,一个是传进函数的拷贝。在对这个zval进行更改之前,把它从一个非引用的集合中分离出来是很必要的。
使用/会很方便,它会自动的把任何copy-on-write引用(也就是假引用的)的变量分离出来。
这个特性跟NULL标志位一样,需要的时候才用到。
zend_get_parameters():
如果想要兼容老版本的php或只想以zval作为载体来接收参数,那么可以考虑使用zend_get_parameters()函数来接收参数
它与zend_parse_parameters()相比,直接获取,不做解析。不会自动进行类型转换,所有参数在扩展实现中的载体都是用zval的.
ZEND_FUNCTION(sample_onearg) {
zval *firstarg; if (zend_get_parameters(ZEND_NUM_ARGS(), 1, &firstarg)== FAILURE) { php_error_docref(NULL TSRMLS_CC, E_WARNING,"Expected at least 1 parameter."); RETURN_NULL(); } /* Do something with firstarg... */ }
同时,它在接收失败的时候不会自己抛出错误,也不能处理具有默认值的参数,最后一点跟parse不同的地方在于它会自动的把所有符合copy-on-write的zval进行强制分离,生成一个崭新的拷贝送到函数内部。
如果不需要这个功能可以用zend_get_parameters_ex()它的参数是zval**的
ZEND_FUNCTION(sample_onearg) { zval **firstarg; if (zend_get_parameters_ex(1, &firstarg) == FAILURE) { WRONG_PARAM_COUNT;抛出一个E_WARNING级别的错误信息,并自动return。 } /*
可变参数,处理任意数目的参数:
还有两种zend_get_parameters_**函数,专门用来解决很多或者无法提前知道参数数目的情况。php语言中的var_dump()函数,可以输入任意数量的参数。
ZEND_FUNCTION(var_dump) { int i, argc = ZEND_NUM_ARGS(); zval ***args; args = (zval ***)safe_emalloc(argc, sizeof(zval **), 0); if (ZEND_NUM_ARGS() == 0 || zend_get_parameters_array_ex(argc, args) == FAILURE) { efree(args); WRONG_PARAM_COUNT; } for (i=0; i<br> 程序首先获取参数数量,然后通过safe_emalloc函数申请相应大小的内存来存储这些zval**的参数。这里使用zend_get_parameters_array_ex()函数来把传递给函数的参数填充到args中。提醒一下,还存在一个zend_get_parameters_array()函数,唯一不同是它将zval*类型的参数填充到args中,并且需要ZEND_NUM_ARGS()作为参数。<br> </p> <p><br> </p> <p><br> </p> <p><strong>2. Arg info参数和类型的绑定</strong></p> <p>这个arg info结构是ZE2才有的。每一个arg info声明都由一个ZEND_BEGIN_ARG_INFO()或ZEND_BEGIN_ARG_INFO_EX()宏组成,后面跟着0个或多个ZEND_ARG_*INFO(), 然后最后以ZEND_END_ARG_INFO()作为结尾。<br> 假定要重写count()函数:<br> </p> <p><pre class="code">PHP_FUNCTION(sample_count_array) { zval *arr; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &arr) == FAILURE) { RETURN_NULL(); } RETURN_LONG(zend_hash_num_elements(Z_ARRVAL_P(arr))); }
zend_parse_parameters()会确保输入到你函数中的参数是一个数组。但是如果你需要用zend_get_parameter()的话,那么就需要自己在函数内部内建类型检查。除非使用类型绑定:
ZEND_BEGIN_ARG_INFO(php_sample_array_arginfo, 0) ZEND_ARG_ARRAY_INFO(0, "arr", 0) ZEND_END_ARG_INFO() 。。。 PHP_FE(sample_count_array, php_sample_array_arginfo) 。。。
通过这种方式,zend engine就会帮你进行类型检查了。同时还给了参数一个名字,从而使得产生的错误信息更加具有可读性。
而对于对象来说,也可以通过arg info进行限定:
ZEND_BEGIN_ARG_INFO(php_sample_class_arginfo, 0) ZEND_ARG_OBJECT_INFO(1, "obj", "stdClass", 0) ZEND_END_ARG_INFO()
这里第一个参数被设为1,表示是引用方式传递,但是对象其实在ZE2中都是引用传递的。不要忘记了array和object的allow_null选项。
如果使用的是php4的话,只能用PHP_TYPE_P()进行检查,或使用convert_to_type()方法进行类型转换。

Heiße KI -Werkzeuge

Undresser.AI Undress
KI-gestützte App zum Erstellen realistischer Aktfotos

AI Clothes Remover
Online-KI-Tool zum Entfernen von Kleidung aus Fotos.

Undress AI Tool
Ausziehbilder kostenlos

Clothoff.io
KI-Kleiderentferner

AI Hentai Generator
Erstellen Sie kostenlos Ai Hentai.

Heißer Artikel

Heiße Werkzeuge

Notepad++7.3.1
Einfach zu bedienender und kostenloser Code-Editor

SublimeText3 chinesische Version
Chinesische Version, sehr einfach zu bedienen

Senden Sie Studio 13.0.1
Leistungsstarke integrierte PHP-Entwicklungsumgebung

Dreamweaver CS6
Visuelle Webentwicklungstools

SublimeText3 Mac-Version
Codebearbeitungssoftware auf Gottesniveau (SublimeText3)

Heiße Themen



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

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

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

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.

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 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).

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

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
