1、生成描述文件,包含对函数等的定义

[chengyi@localhost php-extension]$ cat hello_cy.def

string self_concat(string str, int n);

2、进入PHP源码的ext目录

[chengyi@localhost ext]$ pwd

/home/chengyi/centos_soft_install/php-5.2.5/ext

3、查看ext_skel的帮助,我们主要用到的是 --extname=module  定义将要生成的模块名称; --proto=file    指向刚才的描述函数定义的文件。

[chengyi@localhost ext]$ ./ext_skel --help

./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

--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

4、执行ext_skel,生成空模块

[chengyi@localhost ext]$ ./ext_skel --extname=hello_cy --proto=/home/chengyi/test-all/php-extension/hello_cy.def

Creating directory hello_cy

awk: /home/chengyi/centos_soft_install/php-5.2.5/ext/skeleton/create_stubs:56: warning: escape sequence `/|' treated as plain `|'

Creating basic files: config.m4 config.w32 .cvsignore hello_cy.c php_hello_cy.h CREDITS EXPERIMENTAL tests/001.phpt hello_cy.php [done].

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

1.  $ cd ..

2.  $ vi ext/hello_cy/config.m4

3.  $ ./buildconf

4.  $ ./configure --[with|enable]-hello_cy

5.  $ make

6.  $ ./php -f ext/hello_cy/hello_cy.php

7.  $ vi ext/hello_cy/hello_cy.c

8.  $ make

Repeat steps 3-6 until you are satisfied with ext/hello_cy/config.m4 and

step 6 confirms that your module is compiled into PHP. Then, start writing

code and repeat the last two steps as often as necessary.

5、将生成的空模块mv到自己的目录下去(这里我们没有按照上面ext_skel的说明来做)

[chengyi@localhost ext]$ mv hello_cy/ ~/test-all/php-extension/

6、进入到空模块下,查看都生成了哪些文件

[chengyi@localhost hello_cy]$ ls -p

config.m4  config.w32  CREDITS  EXPERIMENTAL  hello_cy.c  hello_cy.php  php_hello_cy.h  tests/

可以看到,有一个tests目录。

7、修改config.m4文件,打开编译选项

PHP_ARG_ENABLE(hello_cy, whether to enable hello_cy support,

[  --enable-hello_cy           Enable hello_cy support])

if test "$PHP_HELLO_CY" != "no"; then

AC_DEFINE(HAVE_HELLO_CY, 1, [Whether you have Hello World])

PHP_NEW_EXTENSION(hello_cy, hello_cy.c, $ext_shared)

fi

8、执行phpize生成更多文件,为编译做准备

[chengyi@localhost hello_cy]$ phpize

Configuring for:

PHP Api Version:         20041225

Zend Module Api No:      20060613

Zend Extension Api No:   220060519

[chengyi@localhost hello_cy]$ ls

acinclude.m4    build         config.m4   configure.in  EXPERIMENTAL  install-sh       missing         run-tests.php

aclocal.m4      config.guess  config.sub  config.w32    hello_cy.c    ltmain.sh        mkinstalldirs   tests

autom4te.cache  config.h.in   configure   CREDITS       hello_cy.php  Makefile.global  php_hello_cy.h

9、开始编译

./configure --enable-hello_cy

make

make test

sudo make install (有时php ext路径不对,就手工cp过去)

10、测试

[chengyi@localhost hello_cy]$ php hello_cy.php

Functions available in the test extension:

confirm_hello_cy_compiled

self_concat

Congratulations! You have successfully modified ext/hello_cy/config.m4. Module hello_cy is now compiled into PHP.

11、如果想要重新获取到一个干净的目录,执行 phpize --clean

12、将扩展加载,修改php.ini文件

如果不确定php.ini的位置,执行如下:

[chengyi@localhost hello_cy]$ php -i|grep "php.ini"

Configuration File (php.ini) Path => /usr/local/php/lib

Loaded Configuration File => /usr/local/php/lib/php.ini

可以看到,该文件在/usr/local/php/lib/php.ini。

在该文件中添加: extension=hello_cy.so

然后重启apache,如果需要在web端执行的话(如果仅在本地脚本执行,则不用重启apache,因为压根没关系)。

-----------------------------------------------------

探求代码为什么这么写呢?

首先要声明,探求这些只能去PHP的源码看了。源码中比较重要的两个目录是main和Zend。

1、PHP_FUNCTION(self_concat){} 是个什么东西?为什么要用它来定义我们的函数呢?

我们在里面找寻PHP_FUNCTION的定义,在main/下:

php.h:#define PHP_FUNCTION                      ZEND_FUNCTION

然后我们去Zend/目录下,发现了 ZEND_FUNCTION的定义:

zend_API.h:#define ZEND_FUNCTION(name)                          ZEND_NAMED_FUNCTION(ZEND_FN(name))

然后继续由 ZEND_NAMED_FUNCTION, ZEND_FN的定义追查下去得到: void zif_name(INTERNAL_FUNCTION_PARAMETERS)

再看INTERNAL_FUNCTION_PARAMETERS (其实php源码下都有tags,直接ctrl+]就可以跟踪定义了),得到完整的函数定义:

void zif_name(int ht, zval *return_value, zval **return_value_ptr, zval *this_ptr, int return_value_used TSRMLS_DC); // 其实我还蛮好奇这几个参数为什么要这样设置的,等有空去仔细看源码

2、怎样返回值?

我们经常使用的返回值的宏是 RETURN_STRING之类的,去Zend/下找它的定义:

#define RETURN_STRING(s, duplicate)     { RETVAL_STRING(s, duplicate); return; }

#define RETVAL_STRING(s, duplicate)         ZVAL_STRING(return_value, s, duplicate)

可以看出,是给函数定义的参数return_value赋值了,然后估计是由PHP内部的机制,直接把return_value返回。

PHP扩展编写示例的更多相关文章

  1. 老李推荐:第3章3节《MonkeyRunner源码剖析》脚本编写示例: MonkeyImage API使用示例 1

    老李推荐:第3章3节<MonkeyRunner源码剖析>脚本编写示例: MonkeyImage API使用示例   在上一节的第一个“增加日记”的示例中,我们并没有看到日记是否真的增加成功 ...

  2. 老李推荐: 第3章1节《MonkeyRunner源码剖析》脚本编写示例: MonkeyRunner API使用示例

    老李推荐: 第3章1节<MonkeyRunner源码剖析>脚本编写示例: MonkeyRunner API使用示例   MonkeyRunner这个类可以说是编写monkeyrunner脚 ...

  3. PHP扩展编写、PHP扩展调试、VLD源码分析、基于嵌入式Embed SAPI实现opcode查看

    catalogue . 编译PHP源码 . 扩展结构.优缺点 . 使用PHP原生扩展框架wizard ext_skel编写扩展 . 编译安装VLD . Debug调试VLD . VLD源码分析 . 嵌 ...

  4. 第3章3节《MonkeyRunner源码剖析》脚本编写示例: MonkeyImage API使用示例(原创)

    天地会珠海分舵注:本来这一系列是准备出一本书的,详情请见早前博文“寻求合作伙伴编写<深入理解 MonkeyRunner>书籍“.但因为诸多原因,没有如愿.所以这里把草稿分享出来,所以错误在 ...

  5. 第3章2节《MonkeyRunner源码剖析》脚本编写示例: MonkeyDevice API使用示例(原创)

    天地会珠海分舵注:本来这一系列是准备出一本书的,详情请见早前博文“寻求合作伙伴编写<深入理解 MonkeyRunner>书籍“.但因为诸多原因,没有如愿.所以这里把草稿分享出来,所以错误在 ...

  6. 第3章1节《MonkeyRunner源码剖析》脚本编写示例: MonkeyRunner API使用示例(原创)

    天地会珠海分舵注:本来这一系列是准备出一本书的,详情请见早前博文“寻求合作伙伴编写<深入理解 MonkeyRunner>书籍“.但因为诸多原因,没有如愿.所以这里把草稿分享出来,所以错误在 ...

  7. Chrome浏览器扩展开发系列之十九:扩展开发示例

    翻译总结了这么多的官网内容,下面以一款博主开发的“沪深股票价格变化实时追踪提醒”软件为例,介绍Chrome浏览器扩展程序的开发,开发环境为Eclipse IDE+Chrome Browser. “沪深 ...

  8. GDAL库进度信息编写示例

    GDAL进度信息编写 GDAL库中的算法以及读写数据的时候一般都会提供两个与进度信息相关的参数,下面分别进行描述: GDALProgressFunc pfnProgress void * pProgr ...

  9. Slickflow.NET 开源工作流引擎快速入门之三: 简单或分支流程代码编写示例

    前言:对于急切想了解引擎功能的开发人员,在下载版本后,就想尝试编写代码,完成一个流程的开发和测试.本文试图从请假流程,或分支模式来快速了解引擎代码的编写. 1. 创建或分支流程图形 或分支流程是常见的 ...

随机推荐

  1. HashMap(JDK1.8)源码剖析

    在JDK1.6中,HashMap采用位桶+链表实现,即使用链表处理冲突,同一hash值的Entity都存储在一个链表里.但是当位于一个桶中的元素较多,即hash值相等的元素较多时,通过key值依次查找 ...

  2. 到目前为止,Linux下最完整的Samba服务器配置攻略

    关 于Samba,大家有没有这种感觉,弄了N久丫的死活不喘气儿.找来各种“哥”和“姐”,发现全是“详解…配置专题”,看了半天不知道别个在说什么,好不 容易找了个简单的教程,从头到尾跟着做,尼玛,浪费时 ...

  3. CSS 수직 가운데 정렬 (테이블 없이!) Vertical Centering with CSS

    이 방법은 테이블처럼 만들어서 테이블의 vertical-align 속성을 사용할 수 있도록 를 몇 개 세팅한다. (테이블의 vertical-align 속성은 다른 요소들에서는 굉장 ...

  4. 用Cookie记住上次登录用户名

    一个登录页面设置查看Cookie中的数据(Cookie不为null);然后将页面提交到另一个页面去,在这个页面中的到是否选择记住用户名,如果选择了, 就创建Cookie对象,将用户名存储起来,下次登录 ...

  5. 【转】MyBatis学习总结(四)——解决字段名与实体类属性名不相同的冲突

    [转]MyBatis学习总结(四)——解决字段名与实体类属性名不相同的冲突 在平时的开发中,我们表中的字段名和表对应实体类的属性名称不一定都是完全相同的,下面来演示一下这种情况下的如何解决字段名与实体 ...

  6. 比较ASP生成静态HTML文件的几种方法

    将动态页面转换生成静态Html文件有许多好处,比如生成html网页有利于被搜索引擎收录(特别是对接受动态参数的页面).前台访问时,脱离了数据访问,减轻对数据库访问的压力,加快网页打开速度. 当然,凡事 ...

  7. Java语言编写计算器(简单的计算器)

    Java编写的一个简单计算器,本人还比较菜,只能这样了,有点代码冗余,不能连续计算. import javax.swing.*; import java.awt.*; import java.awt. ...

  8. WCF与Web API 区别(应用场景)

    Web api  主要功能: 支持基于Http verb (GET, POST, PUT, DELETE)的CRUD (create, retrieve, update, delete)操作 请求的回 ...

  9. Java编程思想读书笔记--第14章类型信息

    7.动态代理 代理是基本的设计模式之一,它是你为了提供额外的或不同的操作,而插入的用来代替“实际”对象的对象.这些操作通常涉及与“实际”对象的通信,因此代理通常充当着中间人的角色. 什么是代理模式? ...

  10. bzoj2748:[HAOI2012]音量调节

    思路:刷水有益健康. #include<iostream> #include<cstdio> #include<cstring> #include<algor ...