0

0

PHP内核的学习--创建PHP扩展,php内核--扩展_PHP教程

php中文网

php中文网

发布时间:2016-07-13 09:57:22

|

1235人浏览过

|

来源于php中文网

原创

PHP内核的学习--创建PHP扩展,php内核--扩展

开始看PHP内核也有一段时间了,现在开始边学边总结,今天就总结一下如何创建自己的PHP扩展。

我的环境如下:

系统:Ubuntu 14.04

php版本:5.5.19

立即学习PHP免费学习笔记(深入)”;

参考摘录:用C/C++扩展你的PHP

PHP取得成功的一个主要原因之一是它拥有大量的可用扩展。web开发者无论有何种需求,这种需求最有可能在PHP发行包里找到。PHP发行包包括支持各种数据库,图形文件格式,压缩,XML技术扩展在内的许多扩展。

扩展API的引入使PHP3取得了巨大的进展,扩展API机制使PHP开发社区很容易的开发出几十种扩展。现在,两个版本过去了,API仍然和PHP3时的非常相似。扩展主要的思想是:尽可能的从扩展编写者那里隐藏PHP的内部机制和脚本引擎本身,仅仅需要开发者熟悉API。

有两个理由需要自己编写PHP扩展。第一个理由是:PHP需要支持一项她还未支持的技术。这通常包括包裹一些现成的C函数库,以便提供PHP接口。例如,如果一个叫FooBase的数据库已推出市场,你需要建立一个PHP扩展帮助你从PHP里调用FooBase的C函数库。这个工作可能仅由一个人完成,然后被整个PHP社区共享(如果你愿意的话)。第二个不是很普遍的理由是:你需要从性能或功能的原因考虑来编写一些商业逻辑。

假设你正在开发一个网站,需要一个把字符串重复n次的函数。下面是用PHP写的例子:

<span>function</span> <span>util_str_repeat</span>(<span>$string</span>, <span>$n</span><span>){
    </span><span>$result</span> = ""<span>;
    </span><span>for</span>(<span>$i</span> = 0; <span>$i</span> < <span>$n</span>; <span>$i</span>++<span>){
        </span><span>$result</span> .= <span>$string</span><span>;
    }
    </span><span>return</span> <span>$result</span><span>;
}
 
</span><span>util_str_repeat</span>("One", 3);<span>//</span><span> returns "OneOneOne".</span>
<span>util_str_repeat</span>("One", 1);<span>//</span><span> returns "One".</span>

假设由于一些奇怪的原因,你需要时常调用这个函数,而且还要传给函数很长的字符串和大值n。这意味着在脚本里有相当巨大的字符串连接量和内存重新分配过程,以至显著地降低脚本执行速度。如果有一个函数能够更快地分配大量且足够的内存来存放结果字符串,然后把$string重复n次,就不需要在每次循环迭代中分配内存。

为扩展建立函数的第一步是写一个函数定义文件,该函数定义文件定义了扩展对外提供的函数原形。该例中,定义函数只有一行函数原形util_str_repeat() :

<span>string</span> util_str_repeat(<span>string</span> str, <span>int</span> n)

函数定义文件的一般格式是一个函数一行。你可以定义可选参数和使用大量的PHP类型,包括: bool, float, int, array等。

保存为util.def文件至PHP原代码目录树下(即与ext_skel文件放在同一目录下,我的目录是/usr/share/php5/)。

然后就是通过扩展骨架(skeleton)构造器运行函数定义文件的时机了。该构造器脚本就是ext_skel。假设你把函数定义保存在一个叫做util.def的文件里,而且你希望把扩展取名为util,运行下面的命令来建立扩展骨架:

sudo ./ext_skel --extname=util --proto=util.def

执行之后,我这里报了如下错误:

./ext_skel: <span>1</span>: cd: can<span>'</span><span>t cd to /usr/lib/php5/skeleton</span>
<span>Creating directory util
</span><span>awk</span>: cannot open /create_stubs (No such <span>file</span><span> or directory)
Creating basic files: config.m4 config.w32 .svnignore util.c.</span>/ext_skel: <span>216</span>: ./ext_skel: cannot open /skeleton.c: No such <span>file</span><span>
 php_util.h.</span>/ext_skel: <span>234</span>: ./ext_skel: cannot open /php_skeleton.h: No such <span>file</span><span>
 CREDITS.</span>/ext_skel: <span>238</span>: ./ext_skel: cannot open /CREDITS: No such <span>file</span><span>
 EXPERIMENTAL.</span>/ext_skel: <span>242</span>: ./ext_skel: cannot open /EXPERIMENTAL: No such <span>file</span><span>
 tests</span>/<span>001</span>.phpt./ext_skel: <span>247</span>: ./ext_skel: cannot open /tests/<span>001</span>.phpt: No such <span>file</span><span>
 util.php.</span>/ext_skel: <span>251</span>: ./ext_skel: cannot open /skeleton.php: No such <span>file</span>
<span>rm</span>: cannot remove ‘function_entries’: No such <span>file</span><span> or directory
</span><span>rm</span>: cannot remove ‘function_declarations’: No such <span>file</span><span> or directory
</span><span>rm</span>: cannot remove ‘function_stubs’: No such <span>file</span><span> or directory
 [</span><span>done</span><span>].

To use your new extension, you will have to execute the following steps:

</span><span>1</span><span>.  $ cd ..
</span><span>2</span>.  $ <span>vi</span> ext/util/<span>config.m4
</span><span>3</span>.  $ ./<span>buildconf
</span><span>4</span>.  $ ./configure --[with|enable]-<span>util
</span><span>5</span>.  $ <span>make</span>
<span>6</span>.  $ ./php -f ext/util/<span>util.php
</span><span>7</span>.  $ <span>vi</span> ext/util/<span>util.c
</span><span>8</span>.  $ <span>make</span><span>

Repeat steps </span><span>3</span>-<span>6</span> <span>until</span> you are satisfied with ext/util/<span>config.m4 and
step </span><span>6</span><span> confirms that your module is compiled into PHP. Then, start writing
code and repeat the </span><span>last</span> two steps as often as necessary.

很明显是/usr/lib/php5/skeleton路径的错误,编辑ext_skel文件,将/usr/lib/php5/skeleton修改为/usr/share/php5/skeleton,然后移除掉生成的util文件夹,再次执行之前的命令,成功后提示如下:

DiYunCMS(帝云CMS)4.6.2
DiYunCMS(帝云CMS)4.6.2

帝云CMS内容管理系统是基于PHP7语言采用最新CodeIgniter4作为开发框架生产的网站内容管理框架,提供“电脑网站 + 手机网站 + APP 接口”一体化网站技术解决方案。她拥有强大稳定底层框架,以灵活扩展为主的开发理念,二次开发方便且不破坏程序内核,为 WEB 艺术家创造的 PHP 建站程序,堪称 PHP 万能建站框架。

下载
<span>Creating directory util
Creating basic files: config.m4 config.w32 .svnignore util.c php_util.h CREDITS EXPERIMENTAL tests</span>/<span>001</span>.phpt util.php [<span>done</span><span>].

To use your new extension, you will have to execute the following steps:

</span><span>1</span><span>.  $ cd ..
</span><span>2</span>.  $ <span>vi</span> ext/util/<span>config.m4
</span><span>3</span>.  $ ./<span>buildconf
</span><span>4</span>.  $ ./configure --[with|enable]-<span>util
</span><span>5</span>.  $ <span>make</span>
<span>6</span>.  $ ./php -f ext/util/<span>util.php
</span><span>7</span>.  $ <span>vi</span> ext/util/<span>util.c
</span><span>8</span>.  $ <span>make</span><span>

Repeat steps </span><span>3</span>-<span>6</span> <span>until</span> you are satisfied with ext/util/<span>config.m4 and
step </span><span>6</span><span> confirms that your module is compiled into PHP. Then, start writing
code and repeat the </span><span>last</span> two steps as often as necessary.

然后采用静态编译的方式编译扩展。为了使扩展能够被编译,需要修改扩展目录util/下的config.m4文件。扩展没有包裹任何外部的C库,你需要添加支持–enable-util配置开关到PHP编译系统里(–with-extension 开关用于那些需要用户指定相关C库路径的扩展)。找到如下内容:

<span>dnl PHP_ARG_ENABLE(util, whether to enable util support,
dnl Make sure that the comment </span><span>is</span><span> aligned:
dnl [  </span>--enable-util           Enable util support])

将前面的dnl 去掉,修改为如下结果:

<span>PHP_ARG_ENABLE(util, whether to enable util support,
Make sure that the comment </span><span>is</span><span> aligned:
[  </span>--enable-util           Enable util support])

然后修改util.c文件,找到如下代码:

<span>PHP_FUNCTION(util_str_repeat)
{
    </span><span>char</span> *str =<span> NULL;
    </span><span>int</span> argc =<span> ZEND_NUM_ARGS();
    </span><span>int</span><span> str_len;
    </span><span>long</span><span> n;

    </span><span>if</span> (zend_parse_parameters(argc TSRMLS_CC, <span>"</span><span>sl</span><span>"</span>, &str, &str_len, &n) ==<span> FAILURE) 
        </span><span>return</span><span>;

    php_error(E_WARNING, </span><span>"</span><span>util_str_repeat: not yet implemented</span><span>"</span><span>);
}</span>

将其修改为如下代码:

<span>PHP_FUNCTION(util_str_repeat)
{
    </span><span>char</span> *str =<span> NULL;
    </span><span>int</span> argc =<span> ZEND_NUM_ARGS();
    </span><span>int</span><span> str_len;
    </span><span>long</span><span> n;
    </span><span>char</span> *result; <span>/*</span><span> Points to resulting string </span><span>*/</span>
    <span>char</span> *ptr; <span>/*</span><span> Points at the next location we want to copy to </span><span>*/</span>
    <span>int</span> result_length; <span>/*</span><span> Length of resulting string </span><span>*/</span>

    <span>if</span> (zend_parse_parameters(argc TSRMLS_CC, <span>"</span><span>sl</span><span>"</span>, &str, &str_len, &n) ==<span> FAILURE)
        </span><span>return</span><span>;

    </span><span>/*</span><span> Calculate length of result </span><span>*/</span><span>
    result_length </span>= (str_len *<span> n);
    </span><span>/*</span><span> Allocate memory for result </span><span>*/</span><span>
    result </span>= (<span>char</span> *) emalloc(result_length + <span>1</span><span>);
    </span><span>/*</span><span> Point at the beginning of the result </span><span>*/</span><span>
    ptr </span>=<span> result;

    </span><span>while</span> (n--<span>) {
        </span><span>/*</span><span> Copy str to the result </span><span>*/</span><span>
        memcpy(ptr, str, str_len);
        </span><span>/*</span><span> Increment ptr to point at the next position we want to write to </span><span>*/</span><span>
        ptr </span>+=<span> str_len;
    }<br>
    </span><span>/*</span><span> Null terminate the result. Always null-terminate your strings
    even if they are binary strings </span><span>*/</span>
    *ptr = <span>'</span><span>\0</span><span>'</span><span>;
    </span><span>/*</span><span> Return result to the scripting engine without duplicating it</span><span>*/</span><span>
    RETURN_STRINGL(result, result_length, </span><span>0</span><span>);
}</span>

里面的具体内容,就不在这里说了,之后会慢慢写到。

然后就是编译,安装。在util目录下,命令如下(命令可能都需要加sudo):

<span>phpize
.</span>/<span>configure
</span><span>make</span>
<span>make</span><span> test
</span><span>make</span> <span>install</span>

然后配置生成的扩展文件,在php5.5版本中,进入到/etc/php5/mods-available目录下,创建util.ini文件,写入如下内容:

extension=util.so

然后enable util扩展

<span>sudo</span> php5enmod util

最后,重启php-fpm

<span>sudo</span> service php5-fpm restart

创建一个php文件,测试一下,测试文件如下:

<?<span>php
</span><span>for</span> (<span>$i</span> = 1; <span>$i</span> <= 3; <span>$i</span>++<span>) {
    </span><span>print</span> util_str_repeat("CraryPrimitiveMan ", <span>$i</span><span>);
    </span><span>print</span> "\n"<span>;
}
</span>?>

执行结果如下:

<span>CraryPrimitiveMan 
CraryPrimitiveMan CraryPrimitiveMan 
CraryPrimitiveMan CraryPrimitiveMan CraryPrimitiveMan</span>

这样我们就成功创建了一个包含简单的PHP函数的扩展。

盗图一张~~

今天就先到这里~~

 

www.bkjia.comtruehttp://www.bkjia.com/PHPjc/983853.htmlTechArticlePHP内核的学习--创建PHP扩展,php内核--扩展 开始看PHP内核也有一段时间了,现在开始边学边总结,今天就总结一下如何创建自己的PHP扩展。...

相关文章

PHP速学教程(入门到精通)
PHP速学教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
pixiv网页版官网登录与阅读指南_pixiv官网直达入口与在线访问方法
pixiv网页版官网登录与阅读指南_pixiv官网直达入口与在线访问方法

本专题系统整理pixiv网页版官网入口及登录访问方式,涵盖官网登录页面直达路径、在线阅读入口及快速进入方法说明,帮助用户高效找到pixiv官方网站,实现便捷、安全的网页端浏览与账号登录体验。

797

2026.02.13

微博网页版主页入口与登录指南_官方网页端快速访问方法
微博网页版主页入口与登录指南_官方网页端快速访问方法

本专题系统整理微博网页版官方入口及网页端登录方式,涵盖首页直达地址、账号登录流程与常见访问问题说明,帮助用户快速找到微博官网主页,实现便捷、安全的网页端登录与内容浏览体验。

272

2026.02.13

Flutter跨平台开发与状态管理实战
Flutter跨平台开发与状态管理实战

本专题围绕Flutter框架展开,系统讲解跨平台UI构建原理与状态管理方案。内容涵盖Widget生命周期、路由管理、Provider与Bloc状态管理模式、网络请求封装及性能优化技巧。通过实战项目演示,帮助开发者构建流畅、可维护的跨平台移动应用。

144

2026.02.13

TypeScript工程化开发与Vite构建优化实践
TypeScript工程化开发与Vite构建优化实践

本专题面向前端开发者,深入讲解 TypeScript 类型系统与大型项目结构设计方法,并结合 Vite 构建工具优化前端工程化流程。内容包括模块化设计、类型声明管理、代码分割、热更新原理以及构建性能调优。通过完整项目示例,帮助开发者提升代码可维护性与开发效率。

25

2026.02.13

Redis高可用架构与分布式缓存实战
Redis高可用架构与分布式缓存实战

本专题围绕 Redis 在高并发系统中的应用展开,系统讲解主从复制、哨兵机制、Cluster 集群模式及数据分片原理。内容涵盖缓存穿透与雪崩解决方案、分布式锁实现、热点数据优化及持久化策略。通过真实业务场景演示,帮助开发者构建高可用、可扩展的分布式缓存系统。

92

2026.02.13

c语言 数据类型
c语言 数据类型

本专题整合了c语言数据类型相关内容,阅读专题下面的文章了解更多详细内容。

53

2026.02.12

雨课堂网页版登录入口与使用指南_官方在线教学平台访问方法
雨课堂网页版登录入口与使用指南_官方在线教学平台访问方法

本专题系统整理雨课堂网页版官方入口及在线登录方式,涵盖账号登录流程、官方直连入口及平台访问方法说明,帮助师生用户快速进入雨课堂在线教学平台,实现便捷、高效的课程学习与教学管理体验。

15

2026.02.12

豆包AI网页版入口与智能创作指南_官方在线写作与图片生成使用方法
豆包AI网页版入口与智能创作指南_官方在线写作与图片生成使用方法

本专题汇总豆包AI官方网页版入口及在线使用方式,涵盖智能写作工具、图片生成体验入口和官网登录方法,帮助用户快速直达豆包AI平台,高效完成文本创作与AI生图任务,实现便捷智能创作体验。

717

2026.02.12

PostgreSQL性能优化与索引调优实战
PostgreSQL性能优化与索引调优实战

本专题面向后端开发与数据库工程师,深入讲解 PostgreSQL 查询优化原理与索引机制。内容包括执行计划分析、常见索引类型对比、慢查询优化策略、事务隔离级别以及高并发场景下的性能调优技巧。通过实战案例解析,帮助开发者提升数据库响应速度与系统稳定性。

64

2026.02.12

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
PHP课程
PHP课程

共137课时 | 12.2万人学习

JavaScript ES5基础线上课程教学
JavaScript ES5基础线上课程教学

共6课时 | 11.3万人学习

PHP新手语法线上课程教学
PHP新手语法线上课程教学

共13课时 | 0.9万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号