php7.4自定义扩展的编写Lunix篇

php扩展编写的文章很多,但是进入php7.4以后,以前的ext_skel变成了ext_skel.php,而且语法也不一样了,具体的方法也大有不同,不要急,我们这里来讲一个简单扩展的写法,你发发现其实一切并没有变得更复杂,而是变得更简单了

一、编译安装php7.4

ext_skel.php必须要依靠php才能运行,那就必须先编译安装php,相关的安装我就不详细讲了,可以参考我的另一篇文章
https://blog.csdn.net/weixin_48803304/article/details/108600932

二、生成扩展框架

进入php的编译目录

cd php-7.4.10/ext
ls

可以看到ext_skel.php文件

bcmath    com_dotnet  date  enchant       ffi       ftp      gmp    imap  ldap      mysqli   odbc     pcntl  pdo_dblib     pdo_oci    pdo_sqlite  posix     reflection  simplexml  soap     spl       sysvmsg  tidy       xmlreader  xsl        zlib
bz2       ctype       dba   exif          fileinfo  gd       hash   intl  libxml    mysqlnd  opcache  pcre   pdo_firebird  pdo_odbc   pgsql       pspell    session     skeleton   sockets  sqlite3   sysvsem  tokenizer  xmlrpc     zend_test
calendar  curl        dom   ext_skel.php  filter    gettext  iconv  json  mbstring  oci8     openssl  pdo    pdo_mysql     pdo_pgsql  phar        readline  shmop       snmp       sodium   standard  sysvshm  xml        xmlwriter  zip

注意,以前的命令为./ext_skel --extname=扩展名,已经不能用了,要用–ext
我编写的是一个支付加密扩展,命名为lzpay

./ext_skel.php --ext lzpay

成功后可以看到相应的提示

Copying config scripts... done
Copying sources... done
Copying tests... done

Success. The extension is now ready to be compiled. To do so, use the
following steps:

cd /path/to/php-src/lzpay
phpize
./configure
make

Don't forget to run tests once the compilation is done:
make test

Thank you for using PHP!

三、框架扩展说明

1、进入框架目录

cd lzpay

可以看到目录列表

-rw-r--r-- 1 root root 3231 Sep 17 10:44 config.m4
-rw-r--r-- 1 root root  204 Sep 17 10:44 config.w32
-rw-r--r-- 1 root root 2239 Sep 17 10:51 lzpay.c
-rw-r--r-- 1 root root  309 Sep 17 10:44 php_lzpay.h
drwxr-xr-x 2 root root 4096 Sep 17 10:44 tests

2、文件简要
config.m4配置文件
开发PHP扩展,在写C代码之前,要先配置一下这里。我们打开可以看到详细的注释说明,dnl是注释语法。
如果你的扩展用到了外部依赖,就配置–with-lzpay选项,否则配置–enable-lzpay选项
PHP_ARG_ENABLE(lzpay, whether to enable lzpay support,
Make sure that the comment is aligned:
[ –enable-lzpay Enable lzpay support])
PHP_ARG_WITH和PHP_ARG_ENABLE这两个宏用来配置configure选项,一个配置需要外部依赖的,另一个配置不需要外部依赖的
配置好的内容,在后面执行configure –help时可以看到。

php_lzpay.h头文件
类似于C语音的头文件,包含了一些自定义的结构和函数声明,在这个demo中暂时不需要改动

lzpay.c代码文件
真正的逻辑代码都在这个文件中,后面会详细介绍。

四、编写代码

1、了解扩展入口
打开lzpay.c文件。
整个扩展的入口是zend_module_entry这个结构,具体的定义可以在Zend目录下的zend_modules.h文件中看到,一共有十几个属性,快速跳过,我们暂时只需要”lzpay”

/* {
   {
   {
    lzpay_module_entry
 */
zend_module_entry lzpay_module_entry = {
   
	STANDARD_MODULE_HEADER,
	"lzpay",					/* Extension name */
	lzpay_functions,			/* zend_function_entry */
	NULL,							/* PHP_MINIT - Module initialization */
	NULL,							/* PHP_MSHUTDOWN - Module shutdown */
	PHP_RINIT(lzpay),			/* PHP_RINIT - Request initialization */
	NULL,							/* PHP_RSHUTDOWN - Request shutdown */
	PHP_MINFO(lzpay),			/* PHP_MINFO - Module info */
	PHP_LZPAY_VERSION,		/* Version */
	STANDARD_MODULE_PROPERTIES
};
/* }}} */

我们来看一下这里,这里有扩展的相关属性和说明
STANDARD_MODULE_HEADER帮我们实现了前面6个属性
lzpay是扩展的名字,
lzpay_functions是扩展包含的全部方法的集合,后面5个宏分别代表5个扩展特定方法
PHP_HELLO_VERSION是扩展的版本号,定义在头文件中,如果需要修改的话直接打开php_lzpay.h找到define PHP_LZPAY_VERSION进行修改
我把版本修改为0.1.8

STANDARD_MODULE_PROPERTIES帮我们实现了剩下的属性
暂时都不需要修改,知道这是一个入口就行。顺着这个入口,我们继续看怎么给扩展添加方法,在lzpay_functions[]方法数组中已经有了2个示例方法lzpay_test1和lzpay_test2,我们参考它写我们的方法,首先我们写一个测试方法,测试通过再写加密和解密方法
2、对现有扩展进行编译
我们查看代码,可以发现lzpay_test1方法运行的话会提示The extension %s is loaded and working!
而lzpay_test1方法可以对你输入的内容进行Hello的问侯,我们进接进行测试,这样可以有利于我们对编写PHP扩展的理解
我们将现有扩展进行编译
使用命令phpize

Configuring for:
PHP Api Version:         20190902
Zend Module Api No:      20190902
Zend Extension Api No:   320190902

我们看一下生成的文件

[root@zl-gz-099 lzpay]# ll
total 592
drwxr-xr-x 2 root root   4096 Sep 17 11:34 autom4te.cache
drwxr-xr-x 2 root root   4096 Sep 17 11:34 build
-rw-r--r-- 1 root root   1545 Sep 17 11:34 config.h.in
-rw-r--r-- 1 root root   3231 Sep 17 10:44 config.m4
-rwxr-xr-x 1 root root 436073 Sep 17 11:34 configure
-rw-r--r-- 1 root root   5082 Sep 17 11:34 configure.ac
-rw-r--r-- 1 root root    204 Sep 17 10:44 config.w32
-rw-r--r-- 1 root root   2239 Sep 17 10:51 lzpay.c
-rw-r--r-- 1 root root    307 Sep 17 11:27 php_lzpay.h
-rw-r--r-- 1 root root 126747 Sep 17 11:34 run-tests.php
drwxr-xr-x 2 root root   4096 Sep 17 10:44 tests

开始编译安装

./configure --with-php-config=/usr/bin/php-config
 make && make install
Build complete.
Don't forget to run 'make test'.

Installing shared extensions:     /usr/lib64/php/extensions/no-debug-non-zts-20190902/

配置php.ini在最后增加扩展
vi /etc/php/php.ini #编辑配置文件,在最后一行添加以下内容
添加
extension=lzpay.so
:wq! #保存退出
重启PHP则配置生效
我们来看一下,很明显成功了
在这里插入图片描述
我们还需要进行运行测试

3、测试扩展
我们来看一下代码

/* {
   {
   {
    void lzpay_test1()
 */
PHP_FUNCTION(lzpay_test1)
{
   
	ZEND_PARSE_PARAMETERS_NONE();

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

这里的方法是lzpay_test1,我们直接在命令行中测试

php -r 'echo lzpay_test1();'

看下输出内容

[root@zl-gz-099 lzpay]# php -r 'echo lzpay_test1();'
The extension lzpay is loaded and working!

很明显我们运行正常,我们再来测试另一个

php -r 'echo lzpay_test2();'
Hello World

带参数试一下

php -r 'echo lzpay_test2("贵客");'
Hello Hello 贵客

向你问好了哟,一切OK,但我们现在要写一个带参数的
4、扩展编写
这里我们来增加一点难度,网上多数是hello world之类的,这里就有个问题,如果我们只是使用到字符处理就多半不会不自定义扩展了,我们来写一个加密处理,也就是把如何加密的这部分隐藏起来,就算有人拿到了你的PHP代码,至少也不知道你这部分逻辑是怎么处理的。
首先我们会使用到md5的类,这里有两个方法,一个是调用系统的共用md5类,这个就有难度了,要求你的C语言能力比较强,因为在调用call_user_function_ex方法时,只能使用zval类型,针对单一的字符处理就已经够要命了,所以,我自己写了一个md5的类,闲话少说,上代码:
md5.h

#ifndef MD5_H
#define MD5_H
 
typedef struct
{
   
	unsigned int count[2];
	unsigned int state[4];
	unsigned char buffer[64];   
}MD5_CTX;
 
 
#define F(x,y,z) ((x & y) | (~x & z))
#define G(x,y,z) ((x & z) | (y & ~z))
#define H(x,y,z) (x^y^z)
#define I(x,y,z) (y ^ (x | ~z))
#define ROTATE_LEFT(x,n) ((x << n) | (x >> (32-n)))
#define FF(a,b,c,d,x,s,ac) \
{ \
	a += F(b,c,d) + x + ac; \
	a = ROTATE_LEFT(a,s); \
	a += b; \
}
#define GG(a,b,c,d,x,s,ac) \
{ \
	a += G(b,c,d) + x + ac; \
	a = ROTATE_LEFT(a,s); \
	a += b; \
}
#define HH(a,b,c,d,x,s,ac) \
{ \
	a += H(b,c,d) + x + ac; \
	a = ROTATE_LEFT(a,s); \
	a += b; \
}
#define II(a,b,c,d,x,s,ac) \
{ \
	a += I(b,c,d) + x + ac; \
	a = ROTATE_LEFT(a,s); \
	a += b; \
}                                            
void MD5Init(MD5_CTX *context);
void MD5Update(MD5_CTX *context,unsigned char *input,unsigned int inputlen);
void MD5Final(unsigned char digest[16],MD5_CTX *context);
void MD5Transform(unsigned int state[4],unsigned char block[64]);
void MD5Encode(unsigned char *output,unsigned int *input,unsigned int len);
void MD5Decode(unsigned int *output,unsigned char *input,unsigned int len);
 
#endif

md5.c

#include <memory.h>
#include "md5.h"
 
unsigned char PADDING[]={
   0x80,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
 
void MD5Init(MD5_CTX *context)
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值