加入收藏 | 设为首页 | 会员中心 | 我要投稿 | RSS
您当前的位置:首页 > 学习资料

PHP扩展开发--编写一个helloWorld扩展

时间:2021-03-21 23:11:45  来源:  作者:
为什么要用C扩展
C是静态编译的,执行效率比PHP代码高很多。同样的运算代码,使用C来开发,性能会比PHP要提升数百倍。
另外C扩展是在进程启动时加载的,PHP代码只能操作Request生命周期的数据,C扩展可操作的范围更广。

创建helloWorld函数
现在我们来创建属于自己的函数 helloWorld(),功能就是输出 Hello World!
  1. vim myfun/php_myfun.h
  2. ##在PHP_FUNCTION(confirm_myfun_compiled); 下追加一行
  3. PHP_FUNCTION(helloWorld);
复制代码
实现helloworld实体
  1. vim myfun/myfun.c
  2. ##zend_function_entry myfun_functions 补充要实现的函数
  3. const zend_function_entry myfun_functions[] = {
  4.         PHP_FE(confirm_myfun_compiled,     NULL)           /* For testing, remove later. */
  5.         PHP_FE(helloWorld,     NULL)  /*这是补充的一行,末尾没有逗号*/
  6.         {NULL, NULL, NULL}      /* Must be the last line in myfun_functions[] */
  7. };
  8. ##在末尾实现helloworld的内容
  9. PHP_FUNCTION(helloWorld)
  10. {
  11.         php_printf("Hello World!\n");
  12.         RETURN_TRUE;
  13. }
  14.  
复制代码
 
头文件分析
  1. #ifndef PHP_MYFUN_H
  2. #define PHP_MYFUN_H
  3. extern zend_module_entry myfun_module_entry;
  4. #define phpext_myfun_ptr &myfun_module_entry
  5. #ifdef PHP_WIN32
  6. #       define PHP_MYFUN_API __declspec(dllexport)
  7. #elif defined(__GNUC__) && __GNUC__ >= 4
  8. #       define PHP_MYFUN_API __attribute__ ((visibility("default")))
  9. #else
  10. #       define PHP_MYFUN_API
  11. #endif
  12. #ifdef ZTS
  13. #include "TSRM.h"
  14. #endif
  15. PHP_MINIT_FUNCTION(myfun); /*当PHP被装载时,模块启动函数即被引擎调用。这使得引擎做一些例如资源类型,注册INI变量等的一次初始化。*/
  16. PHP_MSHUTDOWN_FUNCTION(myfun);  /*当PHP完全关闭时,模块关闭函数即被引擎调用。通常用于注销INI条目*/
  17. PHP_RINIT_FUNCTION(myfun); /*在每次PHP请求开始,请求前启动函数被调用。通常用于管理请求前逻辑。*/
  18. PHP_RSHUTDOWN_FUNCTION(myfun); /*在每次PHP请求结束后,请求前关闭函数被调用。经常应用在清理请求前启动函数的逻辑。*/
  19. PHP_MINFO_FUNCTION(myfun); /*调用phpinfo()时模块信息函数被呼叫,从而打印出模块信息。*/
  20. PHP_FUNCTION(confirm_myfun_compiled);   /* For testing, remove later. */
  21. PHP_FUNCTION(helloWorld);
  22. #ifdef ZTS
  23. #define MYFUN_G(v) TSRMG(myfun_globals_id, zend_myfun_globals *, v)
  24. #else
  25. #define MYFUN_G(v) (myfun_globals.v)
  26. #endif
  27. #endif  /* PHP_MYFUN_H */
复制代码
confirm_myfun_compiled分析
  1. PHP_FUNCTION(confirm_myfun_compiled)  //使用了宏PHP_FUNCTION(),该宏可以生成一个适合于Zend引擎的函数原型
  2. {
  3.         char *arg = NULL;
  4.         int arg_len, len;
  5.         char *strg;
  6.         //获得函数传递的参数
  7.         //第一个参数是传递给函数的参数个数。通常的做法是传给它ZEND_NUM_ARGS()。这是一个表示传递给函数参数总个数的宏。
  8.         //第二个参数是为了线程安全,总是传递TSRMLS_CC宏。
  9.         //第三个参数是一个字符串,指定了函数期望的参数类型,后面紧跟着需要随参数值更新的变量列表。因为PHP采用松散的变量定义和动态的类型判断,这样做就使得把不同类型的参数转化为期望的类型成为可能。例如,如果用户传递一个整数变量,可函数需要一个浮点数,那么zend_parse_parameters()就会自动地把整数转换为相应的浮点数。如果实际值无法转换成期望类型(比如整形到数组形),会触发一个警告。
  10.         /*
  11.          类型指示符
  12.          l   long        符号整数
  13.          d   double      浮点数
  14.          s   char *, int 二进制字符串,长度
  15.          b   zend_bool   逻辑型(1或0)
  16.          r   zval *      资源(文件指针,数据库连接等)
  17.          a   zval *      联合数组
  18.          o   zval *      任何类型的对象
  19.          O   zval *      指定类型的对象。需要提供目标对象的类类型
  20.          z   zval *      无任何操作的zval
  21.         */
  22.         //第四个参数为传递的参数数据的引用
  23.         //第五个参数为传递的参数个数
  24.         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &arg, &arg_len) == FAILURE) {  //获得函数传递的参数
  25.                 return;
  26.         }
  27.         len = spprintf(&strg, 0, "Congratulations! You have successfully modified ext/%.78s/config.m4. Module %.78s is now compiled into PHP.",     "myfun", arg);
  28.         /*
  29.           通过设置RETURN_type()的方式,将返回控制到PHP。下表解释了大多数存在的宏。
  30.           RETVAL_LONG(l)  整数
  31.           RETVAL_BOOL(b)  布尔数(1或0)
  32.           RETVAL_NULL()   NULL
  33.           RETVAL_DOUBLE(d)    浮点数
  34.           RETVAL_STRING(s, dup)   字符串。如果dup为1,引擎会调用estrdup()重复s,使用拷贝。如果dup为0,就使用s
  35.           RETVAL_STRINGL(s, l, dup)   长度为l的字符串值。与上一个宏一样,但因为s的长度被指定,所以速度更快。
  36.           RETVAL_TRUE     返回布尔值true。注意到这个宏没有括号。
  37.           RETVAL_FALSE    返回布尔值false。注意到这个宏没有括号。
  38.           RETVAL_RESOURCE(r)  资源句柄。
  39.         */
  40.         RETURN_STRINGL(strg, len, 0);
  41. }
复制代码


案例2传数据版
  1. PHP_FUNCTION(mb_MessageBox)
  2. {
  3.     char *arg = NULL;
  4.     int arg_len, len;
  5.     char *strg;
  6.  
  7.     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &arg, &arg_len) == FAILURE) {
  8.         return;
  9.     }
  10.  
  11.     len = spprintf(&strg, 0, "<script>alert('%s')</script>",arg); //此处正是输入的js代码
  12.     RETURN_STRINGL(strg, len, 0);
  13. }
复制代码



 
 
 
 
 
  1. 修改caleng_module.c
  2.  
  3. /* {{{ proto int a(int x, int y)
  4.     */  
  5. PHP_FUNCTION(a)  
  6. {  
  7.     int argc = ZEND_NUM_ARGS();  
  8.     int x;  
  9.     int y;  
  10.     int z;  
  11.     if (zend_parse_parameters(argc TSRMLS_CC, "ll", &x, &y) == FAILURE)   
  12.          
  13.         return;  
  14. z=x+y;  
  15.         RETURN_LONG(z);  
  16.   
  17. }  
  18. /* }}} */  
  19.   
  20. /* {{{ proto string b(string str, int n)
  21.     */  
  22. PHP_FUNCTION(b)  
  23. {  
  24.     char *str = NULL;  
  25.     int argc = ZEND_NUM_ARGS();  
  26.     int str_len;  
  27.     long n;  
  28.     char *result;  
  29.     char *ptr;  
  30.     int result_length;  
  31.    
  32.     if (zend_parse_parameters(argc TSRMLS_CC, "sl", &str, &str_len, &n) == FAILURE)  
  33.         return;  
  34.     result_length = str_len * n;  
  35.     result = (char *) emalloc(result_length + 1);  
  36.     ptr = result;  
  37.     while (n--) {  
  38.         memcpy(ptr, str, str_len);  
  39.         ptr += str_len;  
  40.     }  
  41.     *ptr = '\0';  
  42.     RETURN_STRINGL(result, result_length, 0);  
  43.   
  44. }  
  45. /* }}} */
复制代码
 
  1. PHP_FUNCTION(array_square_sum)
  2. {
  3.     zval* array_data;
  4.     HashTable *ht_data;
  5.     int ret;
  6.     char* key;
  7.     uint index;
  8.     zval **pdata;
  9.     double sum = 0;
  10.  
  11.     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &array_data) == FAILURE) {
  12.         return;
  13.     }   
  14.  
  15.     ht_data = Z_ARRVAL_P(array_data);
  16.     zend_hash_internal_pointer_reset(ht_data);
  17.     while ( HASH_KEY_NON_EXISTANT != (ret = zend_hash_get_current_key(ht_data, &key, &index, 0)) ) {
  18.         ret = zend_hash_get_current_data(ht_data, &pdata);
  19.    
  20.         if( Z_TYPE_P(*pdata) == IS_LONG){
  21.             sum +=  Z_LVAL_P(*pdata) *  Z_LVAL_P(*pdata);
  22.         }else {
  23.             RETURN_FALSE;
  24.         }   
  25.         zend_hash_move_forward(ht_data);
  26.     }   
  27.     zend_hash_internal_pointer_end(Z_ARRVAL_P(array_data));
  28.     RETVAL_DOUBLE(sum);
  29.  
复制代码

IkI华陈数据科技
IkI华陈数据科技
IkI华陈数据科技
IkI华陈数据科技
IkI华陈数据科技
 
来顶一下
返回首页
返回首页
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表
推荐资讯
实现php间隔一段时间执行一次某段代码
实现php间隔一段时间
相关文章
    无相关信息
栏目更新
栏目热门