- 论坛徽章:
- 0
|
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.phpErlang的测试代码
- -module(enif_php).
- -export([init/0, hello/2]).
- init() ->
- erlang:load_nif("./enif_php", 0).
- hello(P1,P2) ->
- [P1,P2].
复制代码 enif_php.c 代码:
- #include "erl_nif.h"
- #include "sapi/embed/php_embed.h"
- #define ENIF_BUFF_LEN 256
- static char enif_php_global_buff[ENIF_BUFF_LEN];
- static int enif_buff_len;
- static int enif_is_init = 0;
- // 返回的处理
- static int php_embed_ub_write(const char *str, uint str_length TSRMLS_DC)
- {
- enif_buff_len -= str_length;
- if(enif_buff_len > 0)
- {
- strcat(enif_php_global_buff,str);
- }
- return str_length;
- }
- // 这个函数是必需定义的
- static void php_embed_send_header(sapi_header_struct *sapi_header, void *server_context TSRMLS_DC)
- {
- }
- static int php_embed_startup(sapi_module_struct *sapi_module)
- {
- if (php_module_startup(sapi_module, NULL, 0)==FAILURE) {
- return FAILURE;
- }
- return SUCCESS;
- }
- static EMBED_SAPI_API sapi_module_struct enif_php_sapi_module = {
- "enif_php", /* name */
- "Enif_php Library", /* pretty name */
- php_embed_startup, /* startup */
- php_module_shutdown_wrapper, /* shutdown */
- NULL, /* activate */
- NULL, /* deactivate */
- php_embed_ub_write, /* unbuffered write */
- NULL, /* flush */
- NULL, /* get uid */
- NULL, /* getenv */
- php_error, /* error handler */
- NULL, /* header handler */
- NULL, /* send headers handler */
- php_embed_send_header, /* send header handler */
- NULL, /* read POST data */
- NULL, /* read Cookies */
- NULL, /* register server variables */
- NULL, /* Log message */
- NULL,
- /* Get request time */
- NULL,
- /* Child terminate */
- STANDARD_SAPI_MODULE_PROPERTIES
- };
- int enif_exec(char * fname, char * qstr)
- {
- zend_file_handle file_handle;
- enif_php_global_buff[0] = '\0';
- enif_buff_len = ENIF_BUFF_LEN;
- if(enif_is_init == 0)
- {
- sapi_startup(&enif_php_sapi_module);
- enif_php_sapi_module.startup(&enif_php_sapi_module);
- }
- enif_is_init = 1;
- // 查询参数赋值
- SG(request_info).request_method = "GET";
- SG(request_info).query_string = qstr;
- file_handle.type = ZEND_HANDLE_FILENAME;
- file_handle.filename = fname;
- //file_handle.opened_path = "/var/www/hack_php";
- file_handle.opened_path = NULL;
- file_handle.free_filename = 0;
- php_request_startup(TSRMLS_C);
- php_execute_script(&file_handle TSRMLS_CC);
- php_request_shutdown((void *) 0);
- enif_php_global_buff[ENIF_BUFF_LEN-enif_buff_len] = '\0';
- SG(server_context) = NULL;
- return 0;
- }
- static ERL_NIF_TERM hello(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
- {
- char * fname;
- char * qstr;
- unsigned int fname_len;
- unsigned int qstr_len;
- if(!enif_get_list_length(env, argv[0], &fname_len)){
- return enif_make_badarg(env);
- }
- fname = malloc((fname_len+1)*sizeof(char));
- if (!enif_get_string(env, argv[0], fname,fname_len+1,ERL_NIF_LATIN1)) {
- return enif_make_badarg(env);
- }
- if(!enif_get_list_length(env, argv[1], &qstr_len)){
- return enif_make_badarg(env);
- }
- qstr = malloc((qstr_len+1)*sizeof(char));
- if (!enif_get_string(env, argv[1], qstr,qstr_len+1,ERL_NIF_LATIN1)) {
- return enif_make_badarg(env);
- }
- enif_exec(fname,qstr);
- free(fname);
- free(qstr);
- return enif_make_string(env, enif_php_global_buff, ERL_NIF_LATIN1);
- }
- static ErlNifFunc nif_funcs[] =
- {
- {"hello", 2, hello}
- };
- ERL_NIF_INIT(enif_php,nif_funcs,NULL,NULL,NULL,NULL)
复制代码 Makefile内容要自行修改
- PHP_PATH = /var/www/hack_php/php-5.3.4/
- CFLAGS = -I$(PHP_PATH) \
- -I$(PHP_PATH)main \
- -I$(PHP_PATH)Zend \
- -I$(PHP_PATH)TSRM \
- -I /usr/local/lib/erlang/usr/include \
- -Wall -g
- LDFLAGS = -L/usr/local/webserver2/php/lib -lphp5
- ALL:
- 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/ |
|