PHP 擴展開發->簡單的擴展開發

目錄

1、什麼是PHP擴展

2、開發環境

3、開始開發自己的擴展

3.1 創建一個名爲hello的擴展

3.2 config.m4配置文件

3.3 編寫代碼

4、測試


1、什麼是PHP擴展

php本身帶有86個擴展,擴展是對php語言功能的一個延伸,php的核心由兩部分組成:最底層的 Zend引擎 和 PHP內核 。ze把腳本解析成機器可讀的符號,也會處理內存管理,變量作用域,程序調度。PHP內核則主要涉及主機環境(Apache,IIS,Nginx),處理與主機的通信。

當php提供的功能不能滿足需求的時候,就有兩種辦法實現自己的需求,一是通過PHP函數來解決問題,另一種就是通過擴展來解決。擴展采用C語言開發還能一定程度上解決性能問題。所以對比於函數機制,PHP擴展有以下優點:

1、如果應用注重效率,使用非常複雜的算法,推薦使用PHP擴展。
2、有些系統調用PHP不能直接訪問(如Linux的fork()函數創建進程),需要編寫成PHP擴展。
3、應用不想暴露關鍵代碼,可以創建擴展使用。
4、同時因爲PHP解析器源碼爲C編寫,所以擴展也可以調用許多PHP解析器的函數。

2、開發環境

 Linux、PHP-7.3.4、GCC

cd PHP源碼目錄
./configure --prefix=[自己要安裝的目錄] --enable-debug
make && make install

3、開始開發自己的擴展

3.1 創建一個名爲hello的擴展

到PHP源碼的ext目錄下會有一個ext_skel.php文件,創建一個叫hello的擴展,有的版本的PHP是./ext_skel --extname=hello

php ext_skel.php --ext hello

3.2 config.m4配置文件

開發PHP擴展,在寫C代碼之前,要先配置一下這裏。我們打開可以看到詳細的註釋說明,dnl是註釋語法。

如果你的擴展用到了外部依賴,就配置--with-hello選項,否則配置--enable-hello選項

cd hello
vim config.m4

#刪除這下面3行的del註釋
PHP_ARG_ENABLE(hello, whether to enable hello support,
Make sure that the comment is aligned:
[  --enable-hello           Enable hello support])

PHP_ARG_WITH和PHP_ARG_ENABLE這兩個宏用來配置configure選項,一個配置需要外部依賴,另一個配置不需要外部依賴;

配置好的內容,在後面執行configure --help時可以看到。

 

php_hello.h頭文件

類似於C語音的頭文件,包含了一些自定義的結構和函數聲明,本例中不需要改動。

 

hello.c代碼文件

真正的邏輯代碼都在這個文件中。

3.3 編寫代碼

打開hello.c文件。

整個擴展的入口是zend_module_entry這個結構,具體的定義可以在Zend目錄下的zend_modules.h文件中看到,一共有十幾個屬性,快速跳過,我們暫時只需要"hello"。

zend_module_entry hello_module_entry = {
	STANDARD_MODULE_HEADER,
	"hello",					/* Extension name */
	hello_functions,			/* zend_function_entry */
	NULL,							/* PHP_MINIT - Module initialization */
	NULL,							/* PHP_MSHUTDOWN - Module shutdown */
	PHP_RINIT(hello),			/* PHP_RINIT - Request initialization */
	NULL,							/* PHP_RSHUTDOWN - Request shutdown */
	PHP_MINFO(hello),			/* PHP_MINFO - Module info */
	PHP_HELLO_VERSION,		/* Version */
	STANDARD_MODULE_PROPERTIES
};
  • STANDARD_MODULE_HEADER幫我們實現了前面6個屬性
  • "hello"是擴展的名字
  • hello_functions是擴展包含的全部方法的集合
  • 後面5個宏分別代表5個擴展特定方法
  • PHP_HELLO_VERSION是擴展的版本號,定義在頭文件中
  • STANDARD_MODULE_PROPERTIES幫我們實現了剩下的屬性

暫時都不需要修改,知道這是一個入口就行。順着這個入口,我們繼續看怎麼給擴展添加方法,在hello_functions[]方法數組中已經有了一個示例方法confirm_hello_compiled,我們參考它寫我們的方法hello_world。

編譯列表

static const zend_function_entry hello_functions[] = {
	PHP_FE(hello_test1,		arginfo_hello_test1)
	PHP_FE(hello_test2,		arginfo_hello_test2)
	PHP_FE(hello_world, NULL)   //我們自定義的方法
	PHP_FE_END
};

功能實現 

PHP_FUNCTION(hello_world)
{
	php_printf("Hello World!\n");
	RETURN_TRUE;
}

編譯與安裝

$ /PHP安裝目錄/bin/phpize

#第一個參數是依賴部件,不加如果調用了PHP內部函數將編譯不了,第二個是設置DEBUG
$ ./configure --with-php-config=/PHP安裝目錄/bin/php-config --enable-debug

$ make & make install

 之後會顯示這個.so文件在哪裏,這時我們只需要在php.ini中添加上擴展的配置

extension = hello.so

4、測試

寫一個test.php方法,執行腳本就可以看到"Hello World!"

<?php
    hello_world();
?>

實際上自動生成的hello.c裏面已經有兩個例子了hello_test1教你如何直接輸出,原理同hello_world;

PHP_FUNCTION(hello_test1)
{
	ZEND_PARSE_PARAMETERS_NONE();

	php_printf("The extension %s is loaded and working!\r\n", "hello");
}

PHP_FUNCTION(hello_test2)
{
	char *var = "World";
	size_t var_len = sizeof("World") - 1;
	zend_string *retval;
    
    //參數解析
	ZEND_PARSE_PARAMETERS_START(0, 1)
		Z_PARAM_OPTIONAL
		Z_PARAM_STRING(var, var_len)
	ZEND_PARSE_PARAMETERS_END();

	retval = strpprintf(0, "Hello %s", var);

	RETURN_STR(retval);
}

hello_test2將你如何輸入參數,參數解析方法已經定義好了,運行測試看看結果

<?php
	echo hello_test2("heheda\n");
 ?>

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章