Linux 下PHP扩展开发系列:二. 一个典型的扩展开发
看完前言中所说的一些内容后,各位应该对PHP扩展开发有个笼统的了解了,可能有些人会觉得开发扩展很麻烦很复杂,实际上并非如此,这一篇我们就快速进入角色,开发出我们的第一个扩展。
一、编译PHP
开发之前还需要先准备好PHP源码并编译,过程如下:
tar -zxvf php-5.3.9.tar.gzcd php-5.3.9
我使用的是php5.3.9,解压后,我们进入了PHP源码目录,然后我们直接编译并增加php.ini:
./configure --prefix=/usr/local/webserver/php --enable-fastcgi --enable-fpm --enable-debugmake && make installcp /home/soft/php-5.3.9/php.ini-development /usr/local/webserver/php/lib/php.ini
编译完成,我没有静态编译其他扩展,但是开启了debug,这个后面会用到。然后修改php.ini中对应的项,这里就不细说了。
现在把PHP相关加入环境变量中,省去后面很多工作:
vim /root/.bash_profile
我是使用root,其他不同用户修改对应用户目录下的.bask_profile文件,在文件中的PATH后面加入:/usr/local/webserver/php/bin/,类似下面这样:
PATH=$PATH:$HOME/bin:/usr/local/webserver/php/bin/
环境变量设置好了,我们查看下PHP版本:
OK,编译工作完成,让我们继续。
二、典型开发流程
一个典型的扩展开发流程如下图:
三、扩展功能定义
先定义我们要完成的扩展功能:
该扩展只有一个功能,就是重写PHP的系统函数ip2long(),解决ip2long在32位与64位系统下值不同的问题(该问题是因为32位与64位的整形范围不同导致的,具体原因请google)。
我们新的ip2long固定返回32位有符号整数,范围-2147483648 到 2147483647,与32位系统相同。
我们的扩展名称为 myip,函数名为 ip2long32
扩展的功能与名称都OK了,现在按流程进行开发。
四、正式开发
1. 生成开发骨架
首先进入源码扩展目录:
cd /home/soft/php-5.3.9/ext
然后了解下PHP提供的扩展骨架工具ext_skel生成骨架,ext_skel的用法如下:
./ext_skel --extname=module [--proto=file] [--stubs=file] [--xml[=file]] [--skel=dir] [--full-xml] [--no-help] --extname=module module is the name of your extension(模块名,会在当前目录创建一个该名称子目录) --proto=file file contains prototypes of functions to create(函数原型定义文件) --stubs=file generate only function stubs in file --xml generate xml documentation to be added to phpdoc-cvs --skel=dir path to the skeleton directory(设置骨架生成的目录,不设置该项则默认在ext/extname下) --full-xml generate xml documentation for a self-contained extension (not yet implemented) --no-help don't try to be nice and create comments in the code and helper functions to test if the module compiled (生成的代码中不显示各种帮助注释)
这次我们准备用到两个选项,--extname=myip 即定义扩展的名称,而--proto=myip.pro则是定义扩展的函数原型,首先我们生成扩展函数原型文件:
vim myip.pro
加入以下内容:
int ip2long32(string ip)
这意味着我们的扩展中有一个函数,返回值为int型,输入为string。
这时候执行以下命令生成扩展骨架:
./ext_skel --extname=myip --proto=myip.pro
OK,这时候你会发现在当前PHP扩展目录下生成了一个子目录myip,进入myip看下:
cd myipll
你会发现生成了一堆文件,如下图:
此时我们就可以进行第二步了。
2. 修改config.m4
关于config.m4文件的功能,我们留到后面的文章中在详细进行说明,现在只说明要做什么。
使用vim编辑config.m4:
vim config.m4
将16至18行行首的dnl去掉,如下:
具体这样做的原因在后面的文章中会说明,这边我们直接退出并保存config.m4,继续进入下一步。
3. 编码
重头戏来啦,终于可以进入myip.c中进行功能的编码了,一起欢呼下吧!
vim myip.c
找到下图所示的位置:
图中就是扩展骨架工具根据我们提供的函数原型生成的对应函数,此处有几个需要注意的地方:
1. PHP_FUNCTION:是PHP核心定义的一个宏,与ZEND_FUNCTION相同,用于定义扩展函数,实际生成的函数名称为zif_ip2long32。
2. zend_parse_parameters:由于PHP为弱类型语言,而C是强类型,因此需要使用该函数用于接收PHP传入的参数,并进行一定的类型转换,将PHP的变量转为C语言能够辨认的类型。
zend_parse_parameters函数的原型如下:
zend_parse_parameters(int num_args TSRMLS_CC, char *type_spec, …);
参数说明:
num_args:传递给函数的参数个数。通常的做法是使用宏 ZEND_NUM_ARGS()。 TSRMLS_CC:线程安全,总是传递TSRMLS_CC宏。 详解:http://www.54chen.com/php-tech/what-is-tsrmls_cc.html type_spec:第三个参数是一个字符串,指定了函数期望的参数类型 ...:需要随参数值更新的变量列表]type_spec是格式化字符串,其常见的含义如下:
参数 代表着的类型
b Boolean
l Integer 整型
d Floating point 浮点型
s String 字符串
r Resource 资源
a Array 数组
o Object instance 对象
O Object instance of a specified type 特定类型的对象
z Non-specific zval 任意类型~
Z zval**类型
f 表示函数、方法名称
我们将该函数修改为如下内容:
PHP_FUNCTION(ip2long32) { char *ip = NULL; int argc = ZEND_NUM_ARGS(); int ip_len; if (zend_parse_parameters(argc TSRMLS_CC, "s", &ip, &ip_len) == FAILURE) { return; } int32_t ip_int32; unsigned char ip1, ip2, ip3, ip4; sscanf(ip, "%hhu.%hhu.%hhu.%hhu", &ip1, &ip2, &ip3, &ip4); ip_int32 = (int32_t)((ip1 << 24) | (ip2 << 16) | (ip3 << 8) | ip4); RETURN_LONG(ip_int32); }
功能完成了,这边有个RETURN_LONG(ip_int32)比较特殊,这也是PHP内核提供的宏,用于返回值给PHP,具体说明如下:
设置返回值并且结束函数 设置返回值 宏返回类型和参数
RETURN_LONG(l) RETVAL_LONG(l) 整数
RETURN_BOOL(b) RETVAL_BOOL(b) 布尔数(1或0)
RETURN_NULL() RETVAL_NULL() NULL
RETURN_DOUBLE(d) RETVAL_DOUBLE(d) 浮点数
RETURN_STRING(s, dup) RETVAL_STRING(s, dup) 字符串。如果dup为1,引擎会调用estrdup()重复s,使用拷贝。如果dup为0,就使用s
RETURN_STRINGL(s, l, dup) RETVAL_STRINGL(s, l, dup) 长度为l的字符串值。与上一个宏一样,但因为s的长度被指定,所以速度更快。
RETURN_TRUE RETVAL_TRUE 返回布尔值true。注意到这个宏没有括号。
RETURN_FALSE RETVAL_FALSE 返回布尔值false。注意到这个宏没有括号。
RETURN_RESOURCE(r) RETVAL_RESOURCE(r) 资源句柄。
编码完成了,保存并退出,然后我们可以开始编译了。
4. 编译
phpize./configure --with-php-config=/usr/local/webserver/php/bin/php-configmake && make install
不出意外的话编译完成后会有如下提示:
Installing shared extensions: /usr/local/webserver/php/lib/php/extensions/debug-non-zts-20090626/
进入该目录看下是否已经有myip.so,有的话最后我们就可以修改php.ini载入该so文件
5. 修改php.ini
cd /usr/local/webserver/php/libvim php.ini
修改extension_dir,并加入 extension = myip.so
extension_dir = "/usr/local/webserver/php/lib/php/extensions/debug-non-zts-20090626/"extension = myip.so
退出保存,并重启php,如果是使用Phpfpm的话可以执行如下命令:
kill -USR2 `cat /usr/local/webserver/php/var/run/php-fpm.pid`
看下扩展是否正常载入:
[root@tm977 lib]# php -m|grep myipmyip
说明已经正常载入了,最后我们测试下扩展函数吧!
6. 测试
php -r "var_dump(ip2long32('192.168.1.1'));"int(-1062731519)php -r "var_dump(ip2long('192.168.1.1'));" int(3232235777)
如上所示,ip2long32输出的是32位有符号整数,而ip2long输出的是64位无符号整数,大功告成!
五、小结
通过这一次的开发示例,是不是觉得其实开发一个扩展很简单?
确实是的,但是也别高兴的太早了,实际上要开发出功能强大的扩展远不是这么简单的事情,后面的文章我会继续深入,一边开发一边了解更加复杂的PHP核心代码。

핫 AI 도구

Undresser.AI Undress
사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover
사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool
무료로 이미지를 벗다

Clothoff.io
AI 옷 제거제

Video Face Swap
완전히 무료인 AI 얼굴 교환 도구를 사용하여 모든 비디오의 얼굴을 쉽게 바꾸세요!

인기 기사

뜨거운 도구

메모장++7.3.1
사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전
중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기
강력한 PHP 통합 개발 환경

드림위버 CS6
시각적 웹 개발 도구

SublimeText3 Mac 버전
신 수준의 코드 편집 소프트웨어(SublimeText3)

뜨거운 주제











Alipay PHP ...

JWT는 주로 신분증 인증 및 정보 교환을 위해 당사자간에 정보를 안전하게 전송하는 데 사용되는 JSON을 기반으로 한 개방형 표준입니다. 1. JWT는 헤더, 페이로드 및 서명의 세 부분으로 구성됩니다. 2. JWT의 작업 원칙에는 세 가지 단계가 포함됩니다. JWT 생성, JWT 확인 및 Parsing Payload. 3. PHP에서 인증에 JWT를 사용하면 JWT를 생성하고 확인할 수 있으며 사용자 역할 및 권한 정보가 고급 사용에 포함될 수 있습니다. 4. 일반적인 오류에는 서명 검증 실패, 토큰 만료 및 대형 페이로드가 포함됩니다. 디버깅 기술에는 디버깅 도구 및 로깅 사용이 포함됩니다. 5. 성능 최적화 및 모범 사례에는 적절한 시그니처 알고리즘 사용, 타당성 기간 설정 합리적,

세션 납치는 다음 단계를 통해 달성 할 수 있습니다. 1. 세션 ID를 얻으십시오. 2. 세션 ID 사용, 3. 세션을 활성 상태로 유지하십시오. PHP에서 세션 납치를 방지하는 방법에는 다음이 포함됩니다. 1. 세션 _regenerate_id () 함수를 사용하여 세션 ID를 재생산합니다. 2. 데이터베이스를 통해 세션 데이터를 저장하십시오.

PHP 개발에서 견고한 원칙의 적용에는 다음이 포함됩니다. 1. 단일 책임 원칙 (SRP) : 각 클래스는 하나의 기능 만 담당합니다. 2. Open and Close Principle (OCP) : 변경은 수정보다는 확장을 통해 달성됩니다. 3. Lisch의 대체 원칙 (LSP) : 서브 클래스는 프로그램 정확도에 영향을 미치지 않고 기본 클래스를 대체 할 수 있습니다. 4. 인터페이스 격리 원리 (ISP) : 의존성 및 사용되지 않은 방법을 피하기 위해 세밀한 인터페이스를 사용하십시오. 5. 의존성 반전 원리 (DIP) : 높고 낮은 수준의 모듈은 추상화에 의존하며 종속성 주입을 통해 구현됩니다.

시스템이 다시 시작된 후 UnixSocket의 권한을 자동으로 설정하는 방법. 시스템이 다시 시작될 때마다 UnixSocket의 권한을 수정하려면 다음 명령을 실행해야합니다.

phpstorm에서 CLI 모드를 디버그하는 방법은 무엇입니까? PHPStorm으로 개발할 때 때때로 CLI (Command Line Interface) 모드에서 PHP를 디버그해야합니다 ...

정적 바인딩 (정적 : :)는 PHP에서 늦은 정적 바인딩 (LSB)을 구현하여 클래스를 정의하는 대신 정적 컨텍스트에서 호출 클래스를 참조 할 수 있습니다. 1) 구문 분석 프로세스는 런타임에 수행됩니다. 2) 상속 관계에서 통화 클래스를 찾아보십시오. 3) 성능 오버 헤드를 가져올 수 있습니다.

PHP 개발에서 PHP의 CURL 라이브러리를 사용하여 JSON 데이터를 보내면 종종 외부 API와 상호 작용해야합니다. 일반적인 방법 중 하나는 컬 라이브러리를 사용하여 게시물을 보내는 것입니다 ...
