免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 4026 | 回复: 0

[其他] 双向扩展,PHP下构建SAPI供Erlang NIF调用 [复制链接]

论坛徽章:
0
发表于 2011-02-11 16:35 |显示全部楼层
NIF做为新版Erlang的一种高效扩展方式非常让人期待,于是闲时尝试用扩展了Erlang实现了对PHP程序的调用,PHP端采用SAPI.

测试内容:
[root@hx enif_php]# make
...
[root@hx enif_php]# erl
...
1> enif_php:init().
ok
2> enif_php:hello("t1.php","q1=45").
"45"




简单测试的php代码 t1.php

  1. echo $_GET['q1'];
复制代码
Erlang的测试代码

  1. -module(enif_php).
  2. -export([init/0, hello/2]).
  3. init() ->
  4.       erlang:load_nif("./enif_php", 0).
  5. hello(P1,P2) ->
  6.       [P1,P2].
复制代码
enif_php.c 代码:

  1. #include "erl_nif.h"
  2. #include "sapi/embed/php_embed.h"

  3. #define ENIF_BUFF_LEN 256
  4. static char enif_php_global_buff[ENIF_BUFF_LEN];
  5. static int enif_buff_len;
  6. static int enif_is_init  = 0;

  7. // 返回的处理
  8. static int php_embed_ub_write(const char *str, uint str_length TSRMLS_DC)
  9. {
  10.     enif_buff_len -= str_length;
  11.     if(enif_buff_len > 0)
  12.     {
  13.        strcat(enif_php_global_buff,str);
  14.     }

  15. return str_length;
  16. }

  17. // 这个函数是必需定义的
  18. static void php_embed_send_header(sapi_header_struct *sapi_header, void *server_context TSRMLS_DC)
  19. {
  20. }


  21. static int php_embed_startup(sapi_module_struct *sapi_module)
  22. {

  23. if (php_module_startup(sapi_module, NULL, 0)==FAILURE) {

  24. return FAILURE;

  25. }

  26. return SUCCESS;
  27. }



  28. static EMBED_SAPI_API sapi_module_struct enif_php_sapi_module = {

  29. "enif_php",                       /* name */

  30. "Enif_php Library",        /* pretty name */


  31. php_embed_startup,              /* startup */

  32. php_module_shutdown_wrapper,   /* shutdown */


  33. NULL,                          /* activate */

  34. NULL,           /* deactivate */


  35. php_embed_ub_write,             /* unbuffered write */

  36. NULL,                /* flush */

  37. NULL,                          /* get uid */

  38. NULL,                          /* getenv */


  39. php_error,                     /* error handler */


  40. NULL,                          /* header handler */

  41. NULL,                          /* send headers handler */

  42. php_embed_send_header,          /* send header handler */


  43. NULL,                          /* read POST data */

  44. NULL,         /* read Cookies */


  45. NULL,   /* register server variables */

  46. NULL,          /* Log message */

  47. NULL,
  48. /* Get request time */

  49. NULL,
  50. /* Child terminate */


  51. STANDARD_SAPI_MODULE_PROPERTIES
  52. };


  53. int enif_exec(char * fname, char * qstr)
  54. {
  55.     zend_file_handle file_handle;
  56.     enif_php_global_buff[0] = '\0';
  57.     enif_buff_len = ENIF_BUFF_LEN;

  58.     if(enif_is_init == 0)
  59.     {
  60.         sapi_startup(&enif_php_sapi_module);
  61.         enif_php_sapi_module.startup(&enif_php_sapi_module);
  62.     }
  63.     enif_is_init = 1;

  64.     // 查询参数赋值

  65. SG(request_info).request_method     = "GET";
  66.     SG(request_info).query_string       = qstr;

  67.     file_handle.type            = ZEND_HANDLE_FILENAME;
  68.     file_handle.filename        = fname;
  69.     //file_handle.opened_path     = "/var/www/hack_php";
  70.     file_handle.opened_path     = NULL;
  71.     file_handle.free_filename   = 0;

  72.     php_request_startup(TSRMLS_C);

  73. php_execute_script(&file_handle TSRMLS_CC);

  74. php_request_shutdown((void *) 0);

  75. enif_php_global_buff[ENIF_BUFF_LEN-enif_buff_len] = '\0';

  76. SG(server_context) = NULL;
  77.     return 0;
  78. }


  79. static ERL_NIF_TERM hello(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
  80. {
  81.     char * fname;
  82.     char * qstr;
  83.     unsigned int fname_len;
  84.     unsigned int qstr_len;

  85.     if(!enif_get_list_length(env, argv[0], &fname_len)){
  86.         return enif_make_badarg(env);
  87.     }
  88.     fname = malloc((fname_len+1)*sizeof(char));
  89.     if (!enif_get_string(env, argv[0], fname,fname_len+1,ERL_NIF_LATIN1)) {
  90.         return enif_make_badarg(env);
  91.     }


  92.     if(!enif_get_list_length(env, argv[1], &qstr_len)){
  93.         return enif_make_badarg(env);
  94.     }
  95.     qstr = malloc((qstr_len+1)*sizeof(char));
  96.     if (!enif_get_string(env, argv[1], qstr,qstr_len+1,ERL_NIF_LATIN1)) {
  97.         return enif_make_badarg(env);
  98.     }

  99.     enif_exec(fname,qstr);
  100.     free(fname);
  101.     free(qstr);
  102.     return enif_make_string(env, enif_php_global_buff, ERL_NIF_LATIN1);
  103. }


  104. static ErlNifFunc nif_funcs[] =
  105. {
  106.     {"hello", 2, hello}
  107. };
  108. ERL_NIF_INIT(enif_php,nif_funcs,NULL,NULL,NULL,NULL)

复制代码
Makefile内容要自行修改

  1. PHP_PATH = /var/www/hack_php/php-5.3.4/
  2. CFLAGS = -I$(PHP_PATH) \
  3.             -I$(PHP_PATH)main \
  4.             -I$(PHP_PATH)Zend \
  5.             -I$(PHP_PATH)TSRM \

  6.     -I /usr/local/lib/erlang/usr/include \
  7.             -Wall -g
  8. LDFLAGS =   -L/usr/local/webserver2/php/lib -lphp5
  9. ALL:

  10. gcc -fPIC -shared -o enif_php.so enif_php.c $(CFLAGS) $(LDFLAGS)
复制代码
本文仅借此实现一些用列,其中存在一些现实问题,如Erlang的NIF调度问题; PHP的线程安全等尚需完善,仅供参考.


Erlang其它对php的访问可参考此前发布过一个Erlang通过fast-cgi方式访问php的例子:
http://lajabs.net/2010/03/12/erl ... %E4%BE%8B%E5%AD%90/
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP