1. 下载php代码
cd /Volumes/Applications/lnmp/src
wget http://am1.php.net/distributions/php-7.3.2.tar.bz2
tar xvjf php-7.3.2.tar.bz2 -C .
cd php-7.3.2
mkdir -p /Volumes/Applications/lnmp/php/7.3.2
./configure --prefix=/Volumes/Applications/lnmp/php/7.3.2
configure: error: Please specify the install prefix of iconv with --with-iconv=<DIR>
2. 下载libiconv
cd /Volumes/Applications/lnmp/src
wget https://ftp.gnu.org/pub/gnu/libiconv/libiconv-1.15.tar.gz
tar xvzf libiconv-1.15.tar.gz -C .
cd libiconv-1.15
./configure --prefix=/Volumes/Applications/lnmp/libiconv-1.15
make
make install
cd ../php-7.3.2
./configure --with-iconv=/Volumes/Applications/lnmp/libiconv-1.15 \
--prefix=/Volumes/Applications/lnmp/php/7.3.2/
make -j4
... 上面的是php源码安装,注意版本对上, 略.
3. 生成扩展模块框架
php 源码目录的ext目录
cd /home/mzh/php/php-7.2.8/ext
./ext_skel --extname=sum
4. 编辑config.m4
cd ./sum
emacs config.m4
PHP_ARG_ENABLE(sum, whether to enable sum support,
[ --enable-sum Enable sum support])
if test "$PHP_SUM" != "no"; then
PHP_NEW_EXTENSION(sum, sum.c, $ext_shared,, -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1)
fi
5. phpize
../../scripts/phpize
6. 扩展模块C代码 sum.c
PHP_FUNCTION(sum) 用PHP_FUNCTION这个宏添加新的函数体. 去掉默认的测试函数.
const zend_function_entry sum_functions[] = {
PHP_FE(sum, NULL) // 新增的函数名添加到这里
PHP_FE_END
};
/* $Id$ */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "php.h"
#include "php_ini.h"
#include "ext/standard/info.h"
#include "php_sum.h"
/* If you declare any globals in php_sum.h uncomment this:
ZEND_DECLARE_MODULE_GLOBALS(sum)
*/
/* True global resources - no need for thread safety here */
static int le_sum;
/* {{{ PHP_INI
*/
/* Remove comments and fill if you need to have entries in php.ini
PHP_INI_BEGIN()
STD_PHP_INI_ENTRY("sum.global_value", "42", PHP_INI_ALL, OnUpdateLong, global_value, zend_sum_globals, sum_globals)
STD_PHP_INI_ENTRY("sum.global_string", "foobar", PHP_INI_ALL, OnUpdateString, global_string, zend_sum_globals, sum_globals)
PHP_INI_END()
*/
/* }}} */
/* Remove the following function when you have successfully modified config.m4
so that your module can be compiled into PHP, it exists only for testing
purposes. */
/* {{{ proto integer sum(array $array)
Take an array of integers and return sum */
PHP_FUNCTION(sum)
{
zval *input;
zval *item;
int32_t total = 0;
HashPosition position;
if (zend_parse_parameters(ZEND_NUM_ARGS(), "a", &input) == FAILURE) {
return;
}
for ( zend_hash_internal_pointer_reset_ex( Z_ARRVAL_P(input), &position );
(item = zend_hash_get_current_data_ex( Z_ARRVAL_P(input), &position) );
zend_hash_move_forward_ex( Z_ARRVAL_P(input), &position ) ) {
if (Z_TYPE_P(item) == IS_LONG) {
total += Z_LVAL_P(item);
} else {
zend_throw_exception(NULL, "ah dear!", 0);
}
}
RETURN_LONG(total);
}
/* }}} */
/* The previous line is meant for vim and emacs, so it can correctly fold and
unfold functions in source code. See the corresponding marks just before
function definition, where the functions purpose is also documented. Please
follow this convention for the convenience of others editing your code.
*/
/* {{{ php_sum_init_globals
*/
/* Uncomment this function if you have INI entries
static void php_sum_init_globals(zend_sum_globals *sum_globals)
{
sum_globals->global_value = 0;
sum_globals->global_string = NULL;
}
*/
/* }}} */
/* {{{ PHP_MINIT_FUNCTION
*/
PHP_MINIT_FUNCTION(sum)
{
/* If you have INI entries, uncomment these lines
REGISTER_INI_ENTRIES();
*/
return SUCCESS;
}
/* }}} */
/* {{{ PHP_MSHUTDOWN_FUNCTION
*/
PHP_MSHUTDOWN_FUNCTION(sum)
{
/* uncomment this line if you have INI entries
UNREGISTER_INI_ENTRIES();
*/
return SUCCESS;
}
/* }}} */
/* Remove if there's nothing to do at request start */
/* {{{ PHP_RINIT_FUNCTION
*/
PHP_RINIT_FUNCTION(sum)
{
#if defined(COMPILE_DL_SUM) && defined(ZTS)
ZEND_TSRMLS_CACHE_UPDATE();
#endif
return SUCCESS;
}
/* }}} */
/* Remove if there's nothing to do at request end */
/* {{{ PHP_RSHUTDOWN_FUNCTION
*/
PHP_RSHUTDOWN_FUNCTION(sum)
{
return SUCCESS;
}
/* }}} */
/* {{{ PHP_MINFO_FUNCTION
*/
PHP_MINFO_FUNCTION(sum)
{
php_info_print_table_start();
php_info_print_table_header(2, "sum support", "enabled");
php_info_print_table_end();
/* Remove comments if you have entries in php.ini
DISPLAY_INI_ENTRIES();
*/
}
/* }}} */
/* {{{ sum_functions[]
*
* Every user visible function must have an entry in sum_functions[].
*/
const zend_function_entry sum_functions[] = {
PHP_FE(sum, NULL)
PHP_FE_END
};
/* }}} */
/* {{{ sum_module_entry
*/
zend_module_entry sum_module_entry = {
STANDARD_MODULE_HEADER,
"sum",
sum_functions,
PHP_MINIT(sum),
PHP_MSHUTDOWN(sum),
PHP_RINIT(sum), /* Replace with NULL if there's nothing to do at request start */
PHP_RSHUTDOWN(sum), /* Replace with NULL if there's nothing to do at request end */
PHP_MINFO(sum),
PHP_SUM_VERSION,
STANDARD_MODULE_PROPERTIES
};
/* }}} */
#ifdef COMPILE_DL_SUM
#ifdef ZTS
ZEND_TSRMLS_CACHE_DEFINE()
#endif
ZEND_GET_MODULE(sum)
#endif
zend_parse_parameters 参考文档: README.PARAMETER_PARSING_API
a - array (zval*)
A - array or object (zval*)
b - boolean (zend_bool)
C - class (zend_class_entry*)
d - double (double)
f - function or array containing php method call info (returned as
zend_fcall_info and zend_fcall_info_cache)
h - array (returned as HashTable*)
H - array or HASH_OF(object) (returned as HashTable*)
l - long (zend_long)
L - long, limits out-of-range numbers to LONG_MAX/LONG_MIN (zend_long, ZEND_LONG_MAX/ZEND_LONG_MIN)
o - object of any type (zval*)
O - object of specific type given by class entry (zval*, zend_class_entry)
p - valid path (string without null bytes in the middle) and its length (char*, size_t)
P - valid path (string without null bytes in the middle) as zend_string (zend_string*)
r - resource (zval*)
s - string (with possible null bytes) and its length (char*, size_t)
S - string (with possible null bytes) as zend_string (zend_string*)
z - the actual zval (zval*)
* - variable arguments list (0 or more)
+ - variable arguments list (1 or more)
* 编译扩展
./configure --prefix=/opt/php/7.2.8 --with-php-config=/opt/php/7.2.8/bin/php-config
make
make install
# 编写扩展模块C代码过程中会重复这一步,直到消除错误.
* 查看当前扩展
php -dextension=sum.so -m
sudo mkdir /etc/php.d/
sudo chown mzh:mzh /etc/php.d
emacs /etc/php.d/sum.ini
extension=sum.so
php -m
* 查看php版本
../../sapi/cli/php -v
PHP 7.2.8 (cli) (built: Nov 12 2018 09:19:51) ( NTS )
Copyright (c) 1997-2018 The PHP Group
Zend Engine v3.2.0, Copyright (c) 1998-2018 Zend Technologies
* 编辑php.ini
extension_dir="/opt/php/7.2.8/lib/php/extensions/no-debug-non-zts-20170718"
extension=sum
扩展路径为make install后目标路径
php -m | grep sum
* 测试新增的php函数 test_sum.php
** test case#1
<?php
$a = array(1,2,3,4,5,6);
$sum = sum($a);
var_dump($sum);
$ php test_sum.php
int(21)
** test case#2
test_sum.php 数组元素添加一个字符串类型的元素, 抛异常 (zend_throw_exception)
<?php
$a = array(1,2,3,4,5,6, 'oh,string');
$sum = sum($a);
var_dump($sum);
$ php test_sum.php
PHP Fatal error: Uncaught Exception: ah dear! in /home/mzh/php/php-7.2.8/ext/sum/test_sum.php:4
Stack trace:
#0 /home/mzh/php/php-7.2.8/ext/sum/test_sum.php(4): sum(Array)
#1 {main}
thrown in /home/mzh/php/php-7.2.8/ext/sum/test_sum.php on line 4