PECL_Gen

    ⼀旦安装完成, 它就可以像ext_skel一样运行, 接受相同的输入参数, 产生大致相同的 输出, 或者如果提供了一个完整的xml定义文件, 则产生一个更加健壮和完整可编译版本的 扩展. PECL_Gen并不会节省你编写扩展核心功能的时间; 而是提供⼀种可选的方式高效 的生成扩展骨架代码.

    specfile.xml

    下面是最简单的扩展定义文件:

    通过PECL_Gen命令运行这个文件:

    1. jdoe@devbox:/home/jdoe/cvs/php-src/ext/$ pecl-gen specfile.xml

    则会产生一个名为sample9的扩展, 并暴露一个用户空间函数sample9_hello_world().

    关于扩展

    除了你已经熟悉的功能文件, PECL_Gen还会产生⼀个package.xml文件 它可以用于 pear安装. 如果你计划发布包到PECL库, 或者哪怕你只是想要使用pear包系统交付内容, 有这个文件都会很有用.

    总之, 你可以在PECL_Gen的specfile.xml中指定多数package.xml文件的元素.

    1. <?xml version="1.0" encoding="UTF-8" ?>
    2. <extension name="sample9">
    3. <summary>Extension 9 generated by PECL_Gen</summary>
    4. <description>Another sample of PHP Extension Writing</description>
    5. <maintainers>
    6. <maintainer>
    7. <name>John D. Bookreader</name>
    8. <email>jdb@example.com</email>
    9. <role>lead</role>
    10. </maintainer>
    11. </maintainers>
    12. <release>
    13. <version>0.1</version>
    14. <date>2006-01-01</date>
    15. <state>beta</state>
    16. <notes>Initial Release</notes>
    17. ...
    18. </extension>

    当PECL_Gen创建扩展时, 这些信息将被翻译到最终的package.xml文件中. 依赖

    依赖

    with

    通常, 扩展在配置时使用—enable-extname样式的配置选项. 通过增加⼀个或多个 标签到块中, 则不仅配置选项被修改为—with-extname, 而且同时需要扫描 头文件:

    1. <deps platform="unix">
    2. <with defaults="/usr:/usr/local:/opt"
    3. testfile="include/zlib/zlib.h">zlib headers</with>
    4. </deps>

    必须的库也列在下, 使用标签.

    1. <deps platform="all">
    2. <lib name="ssleay" platform="win32"/>
    3. <lib name="crypto" platform="unix"/>
    4. </deps>

    在前面两个例子中, 只是检查了库是否存在; 第三个例子中, 库将被真实的加载并扫描 以确认inflate()函数是否定义.

    尽管标签实际已经命名了目标平台, 但标签也有⼀个platform属性可以覆盖 标签的platform设置. 当它们混合使用的时候要格外小心.

    此外, 需要包含的文件也可以通过在块中使用

    标签在你的代码中追 加⼀个#include指令列表. 要强制某个头先包含, 可以在
    标签上增加属性 prepend=”yes”. 和依赖类似,
    也可以严格限制平台:

    1. <deps>
    2. <header name="sys/types.h" platform="unix" prepend="yes"/>
    3. <header name="zlib/zlib.h"/>
    4. </deps>
    5. 译注: 经测试, 译者的环境<header>标签不支持platform属性.

    常量

    用户空间常量使用块中的一个或多个标签定义. 每个标签需 要一个name和⼀个value属性, 以及⼀个值必须是int, float, string之一的type属性.

    全局变量

    1. <globals>
    2. <global name="greeting" type="char *"/>
    3. <global name="greeting_was_issued" type="zend_bool" value="1"/>
    4. </globals>

    INI选项

    要绑定线程安全的全局变量到php.ini设置, 则需要使用标签而不是. 这个标签需要两个额外的参数: onupdate=”updatemethod”标识INI的修改应该怎样处理, access=”mode”和第13章”INI设置”中介绍的模式含义相同, “mode”值可以是: all, user, perdir, system.

    1. <globals>
    2. <phpini name="mysetting" type="int" value="42" onupdate="OnUpdateLong" access="all"/>
    3. </globals>

    函数

    你已经看到了最基本的函数定义; 不过, 标签在PECL_Gen的specfile中实 际上支持两种不同类型的函数.

    两个版本都支持你已经在级别上使用过的

    属 性; 两种类型都必须的元素是标签, 它包含了将要被放入你的源代码文件中的原文C语言代码.

    role=”public”

    如你所想, 所有定义为public角色的函数都将包装恰当的PHP_FUNCTION()头和花括 号, 对应到扩展的函数表向量中的条目.

    除了其他函数支持的标签, public类型还允许指定一个标签. 这个标签的格式 应该匹配php在线手册中的原型展示, 它将被文档生成器解析.

    1. <functions>
    2. <function role="public" name="sample9_greet_me">
    3. <summary>Greet a person by name</summary>
    4. <description>Accept a name parameter as a string and say hello to that person.
    5. Returns TRUE.</description>
    6. <proto>bool sample9_greet_me(string name)</proto>
    7. <code>
    8. <![CDATA[
    9. char *name;
    10. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s",
    11. &name, &name_len) == FAILURE) {
    12. return; }
    13. PHPWRITE(name, name_len);
    14. php_printf("!\n");
    15. RETURN_TRUE;
    16. ]]>
    17. </code>
    18. </function>
    19. </functions>

    role=”internal”

    内部函数涉及5个zend_module_entry函数: MINIT, MSHUTDOWN, RINIT, RSHUTDOWN, MINFO. 如果指定的名字不是这5个之一将会产生pecl-gen无法处理的错误.

    自定义代码

    1. <code role="header" position="bottom">
    2. <![CDATA[
    3. typedef struct _php_sample9_data {
    4. long val;
    5. } php_sample9_data;
    6. ]]>
    7. </code>
    8. <code role="code" position="top">
    9. <![CDATA[
    10. static php_sample9_data *php_sample9_data_ctor(long value)
    11. {
    12. php_sample9_data *ret;
    13. ret = emalloc(sizeof(php_sample9_data));
    14. ret->val = value;
    15. return ret;
    16. }
    17. ]]> </code>
    18. 译注: 译者的环境中不支持原著中<code>标签的name属性.