最近在看 《PHP擴展開發中文教程》
的pdf版。PHP的解釋器是用C語言寫的,因此PHP擴展天然也是用C 語言
了。php
用過php的人必定也用過php擴展。php自己帶有86個擴展,擴展是對php語言功能的一個延伸,php的核心由兩部分組成:最底層的 Zend引擎
和 PHP內核
。ze把腳本解析成機器可讀的符號,也會處理內存管理,變量做用域,程序調度。PHP內核則主要涉及主機環境(Apache,IIS,Nginx),處理與主機的通訊。編程
當php自身不知足需求的時候就能夠本身去造輪子了。採用C語言開發還能必定程度上解決性能問題,而php是我最喜歡的一門編程語言,寫擴展的機會天然不放過,更重要的是能夠 裝逼
。php7
咱們要寫個擴展代替如下的功能:編程語言
<?php function hello() { return 'hello world'; }
個人開發環境是:工具
系統: Ubuntu 16.04性能
PHP: 7.0+測試
gcc :4.8.4
PHP已經提供了工具用來建立擴展,並初始化代碼:ext_skel
spa
$ cd php-src/ext $ ./ext_skel --extname=hello
工具會在當前目錄生成 hello
文件夾。code
cd到hello,工具已經初始化了目錄,打開配置文件 config.m4
:blog
dnl If your extension references something external, use with: dnl PHP_ARG_WITH(hello, for hello support, dnl Make sure that the comment is aligned: dnl [ --with-hello Include hello support]) dnl Otherwise use enable: dnl PHP_ARG_ENABLE(hello, whether to enable hello support, dnl Make sure that the comment is aligned: dnl [ --enable-hello Enable hello support])
dnl 是註釋符,表示當前行是註釋。這段話是說若是此擴展依賴其餘擴展,去掉PHP_ARG_WITH
段的註釋符;不然去掉PHP_ARG_ENABLE
段的註釋符。顯然咱們不依賴其餘擴展或lib庫,因此去掉PHP_ARG_ENABLE
段的註釋符:
PHP_ARG_ENABLE(hello, whether to enable hello support, Make sure that the comment is aligned: [ --enable-hello Enable hello support])
工具生成的hello.c
,寫上咱們的實現:
PHP_FUNCTION(hello) { zend_string *strg; strg = strpprintf(0, "hello world."); RETURN_STR(strg); }
添加到編譯列表裏:
const zend_function_entry hello_functions[] = { PHP_FE(hello, NULL) /*添加這行*/ PHP_FE(confirm_hello_compiled, NULL) /* For testing, remove later. */ PHP_FE_END /* Must be the last line in hello_functions[] */ };
$ phpize $ ./configure --with-php-config=/usr/local/php7/bin/php-config $ make & make install
修改php.ini
,開啓擴展,若找不到能夠用phpinfo()
查看使用哪一個配置文件.
extension=hello.so
寫個腳本:<?php echo hello();
不出意外就能看到輸出了。
一個擴展(爲避免與寫過的hello衝突,採用world做爲名字),至少包含3個文件: config.m4
、 php_world.h
、 world.c
。一個是phpize用來準備編譯擴展的配置文件,一個是引用包含的頭文件,一個是源碼文件。
config.m4
PHP_ARG_ENABLE(world, whether to enable world support, Make sure that the comment is aligned: [ --enable-world Enable hello support]) if test "$PHP_WORLD" != "no"; then AC_DEFINE(HAVE_WORLD,1,[ ]) PHP_NEW_EXTENSION(world, world.c, $ext_shared,, -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1) fi
php_world.h
#ifndef PHP_WORLD_H #define PHP_WORLD_H extern zend_module_entry hello_module_entry; #define phpext_hello_ptr &hello_module_entry #define PHP_WORLD_VERSION "0.1.0" #define PHP_WORLD_EXTNAME "world" #endif
world.c
#ifdef HAVE_CONFIG_H #include "config.h" #endif #include "php.h" #include "php_world.h" PHP_FUNCTION(world) { zend_string *strg; strg = strpprintf(0, "hello world. (from world module)"); RETURN_STR(strg); } const zend_function_entry world_functions[] = { PHP_FE(world, NULL) PHP_FE_END }; zend_module_entry world_module_entry = { STANDARD_MODULE_HEADER, PHP_WORLD_EXTNAME, world_functions, NULL, NULL, NULL, NULL, NULL, PHP_WORLD_VERSION, STANDARD_MODULE_PROPERTIES }; #ifdef COMPILE_DL_WORLD #ifdef ZTS ZEND_TSRMLS_CACHE_DEFINE() #endif ZEND_GET_MODULE(world) #endif
編譯安裝:
$ phpize $ ./configure --with-php-config=/usr/local/php7/bin/php-config $ make & make install
測試:
同樣須要在php.ini
添加extension=world.so
不使用工具的精簡的一個擴展完成。