A failed PHP extension development

Source: Internet
Author: User
Tags php class zend

one failed.PHP Extended development Journey

by Warezhou 2014.11.19


Origin

through continuous iteration, our departmental network framework ( Cosvrframe ) finally baked! This would have been a great rush, but as new business continues to be plugged in, many inherent flaws are emerging:

    • not supported " TCP Connection Pool "
    • not supported " dispatcher-workers Model "
    • "Overload protection" is not supported
    • "Hot restart" is not supported
    • not supported " 64Bit "
    • ... ...

for senior background development, most of the problems listed above are difficult to access, the reason becomes a problem, very little "boiled frog" flavor: The iterative process lacks the macroscopic view, introduces the excessive business characteristic, causes the overall structure unreasonable. The most recent "co-version" is also my personal amateur, just to be able to happily write business code, in order to quickly caller, the bottom of the direct reuse of the original svrframe, the results can be imagined: the foundation is not strong, shake! Take the most extreme 64Bit As an example, I believe you understand the second.

After a lot of research and discussion, we finally give the following direction:

    • the introduction of open source Company internal SPP3.0 Framework, absorbing its infrastructure, conducting business two times development
    • for SPP to expand to support PHP embedded programming as a scripting language, while C extended form to PHP provides the ability to co-process (from this Phper can also happily write the asynchronous code, mother no longer have to worry about my Callback out! )

Jutting forced Jutting long-winded, the following can cut into the topic: how to Achieve c++/php mixed programming?

Disclaimer: As I belong to the halfway decent, contact PHP Extension development has not been enough weeks, so can not go into why , only to stay in How , only for record use, Hope Master forgive me!

opening EmbeddedPHP

Industry c++/php generally for "performance" considerations, PHP called in the code C + + to address specific performance bottlenecks such as PB serialization, etc.).

as a C + + Development Origins, "development efficiency" compared to "performance" the temptation is obviously greater, therefore, our idea is: PHP as a scripting language, quickly develop business logic, insert into SPP The framework runs.

1. open php Dynamic Library in Rtld_global mode

void *php_handler = Dlopen ("libphp5.so", Rtld_lazy | Rtld_global); if (!php_handler) {    base->log_. Log_p_pid (Log_fatal, "%s\n", Dlerror ());    return-1; }   Dlclose (Php_handler);

2. Initializing via php_embed_init

Php_embed_module.php_ini_path_override = ". /php/php.ini ";p hp_embed_init (0, NULL);

3. Introducing PHP scripts via zend_eval_string

zend_first_try {    char exec_str[256];    snprintf (exec_str, sizeof (EXEC_STR), "include '%s ';", "... /php/demo_handler.php ");    if (int ret = zend_eval_string (Exec_str, NULL, Exec_str tsrmls_cc)) {        base->log_. Log_p_pid (Log_fatal, "zend_eval_string fail. ret=%d\n ", ret);        return-1;     }    Base->log_. Log_p_pid (Log_debug, "zend_eval_string succ.\n");} Zend_catch {    Base->log_. Log_p_pid (Log_fatal, "zend_eval_string catch.\n");} Zend_end_try ();

4. callback PHP function via call_user_function

Zval Z_funcname; Zval_string (&z_funcname, "Echodemo::init", 1); Zval *zp_svr; Make_std_zval (ZP_SVR); Zval_long (Zp_svr, (LONG) base); Zval *zp_etc; Make_std_zval (ZP_ETC); Zval_string (ZP_ETC, etc, 1); Zval z_retval;zval *z_params[] = {ZP_SVR, zp_etc};int Call_ret = Call_user_function (CG ( function_table), NULL, &z_funcname, &z_retval, sizeof (z_params)/sizeof (Z_params[0]), Z_params tsrm convert_to _long (&z_retval); int func_ret = Z_lval_p (&z_retval); Zval_ptr_dtor (&ZP_ETC); Zval_dtor (&z_funcname) ; Zval_dtor (&z_retval); if (Call_ret < 0 | | Func_ret < 0) {    base->log_. Log_p_pid (Log_fatal, "call_user_function fail. call_ret=%d func_ret=%d\n ", Call_ret, Func_ret);    return-1;}

5. Cleaning by php_embed_shutdown

Php_embed_shutdown (Tsrmls_c);

PHP Extended

On the web about PHP of the C Extended development articles can be said to have reached the point of flooding, interested readers can read the appendix at the end of the article.

1. Download php Source Package, manual compilation, in order to match the above embedded use, need to open the -enable-embed option

./configure--enable-embedmakemake Install (optional)

2. Go to the ext directory of the PHP source package and generate the plugin shelf code with the ext_skel tool

CD Ext./ext_skel--extname=demo

3. edit config.m4, open php_arg_with or php_arg_ ENABLE option (to tell the truth the difference is still unclear, ask for guidance), add C + + support, dependency path, etc.

Php_arg_enable (demo, whether to enable demo support,    [  --enable-demo           ENABLE Demo support]) if test "$PHP _ DEMO "! =" no "; Then  php_require_cxx ()  php_add_library (stdc++, 1, extra_ldflags)  php_add_include (/root/spp/module/ include/)  php_add_include (/root/spp/module/include/spp_incl/)  php_new_extension (demo, Demo.cpp, $ext _ Shared) fi

4. edit demo.cpp, add extension definitions and implementations (functions, classes, variables ... ) ), here are just examples of function definitions, and interested readers of the class are themselves based on the appendix. The sendrecv function definition Given here is more representative, where the 3 parameter RSP is a reference parameter, Responsible for returning the received data to the PHP caller

ZEND_BEGIN_ARG_INFO_EX (arginfo_sendrecv, 0, 0, 7) zend_arg_info (0, req) zend_arg_info (0, Req_len) zend_arg_info (1 , RSP) zend_arg_info (0, Rsp_len) zend_arg_info (0, IP) zend_arg_info (0, Port) zend_arg_info (0, timeout) zend_end    _arg_info () php_function (sendrecv) {char *req = NULL;    int req_str_len = 0;    Long Req_len = 0;    Zval *rsp = NULL;    Long Rsp_len = 0;    char *ip = NULL;    int ip_str_len = 0;    Long port = 0; Long timeout = 0;if (Zend_parse_parameters (Zend_num_args () tsrmls_cc, "Slzlsll", &req, &req_str_len,&req_       Len, &AMP;RSP, &rsp_len, &ip, &ip_str_len, &port, &timeout) = = FAILURE) {return;}    struct sockaddr_in addr;    memset (&addr, 0, sizeof (addr));    addr.sin_family = af_inet;    ADDR.SIN_ADDR.S_ADDR = inet_addr (std::string (IP, Ip_str_len). C_STR ());    Addr.sin_port = htons (port);    Char *rsp_buf = (char *) emalloc (Rsp_len);    int rsp_buf_len = Rsp_len; if (int ret = MT_UDPSENDRCV (&AMP;ADDR, Req, Req_len > Req_str_len?        Req_str_len:req_len, Rsp_buf, Rsp_buf_len, timeout)) {efree (RSP_BUF);    Return_long (ret);    } zval_dtor (RSP);    Zval_stringl (RSP, Rsp_buf, Rsp_buf_len, 0); Return_long (0);}
Const Zend_function_entry demo_functions[] = {    Php_fe (sendrecv, ARGINFO_SENDRECV)    php_fe_end/  * must be The last line in demo_functions[] */};

5. Everything is ready, can compile the extension, I personally prefer the dynamic compilation (static compilation needs to recompile PHP source code, too time-consuming laborious), generated . In the modules directory of the current extension

/usr/local/bin/phpize./configure--with-php-config=/usr/local/bin/php-configmake

6. Edit the php.ini file, add a new extension, and then happily call the new extension in the PHP code

Extension_dir= "/somewhere/modules" extension= "demo.so" extension= "xxxx.so"

Orgasm

finally it was time to assemble the molding, through telnet played a few. Echodemo , see a line of ECHO, can not help feeling good.

<?php class Echodemo {public static function init ($server, $conf) {log_debug ($server, "Init in P            Hp.\n ");        return true; public static function input ($server, $req, $ext _info = Array ()) {Log_debug ($server, "Input in PHP            . \ n ");        return strlen ($req); The public static function route ($server, $req, $ext _info = Array ()) {Log_debug ($server, "Route in PHP            . \ n ");        return 1;  The public static function process ($server, $req, $ext _info = Array ()) {Log_debug ($server, "process in            Php.\n ");            $ret = Sendrecv ($req, strlen ($req), $RSP, 65535, "127.0.0.1", 2345, 500); if ($ret! = 0) {log_debug ($server, "sendrecv fail.                ret= $ret ");            return false; } log_debug ($server, "Sendrecv finish.            rsp= $rsp ");        return true; } public static function Fini ($server) {Log_debUG ($server, "fini in php.\n"); }}?>

The most amazing thing about it Process function for Sendrecv extension calls, where the behind-the-scenes through the association has actually implemented an asynchronous network interaction: it can be as synchronous CGI To write logic code and enjoy asynchronous high concurrency without pain.

The wish is good, the reality is cruel!

I suddenly whim: to test a performance bar, see compared to the native C + + How much performance attenuation the code has. A single request 1KB, with 1w/s pressure, pressure for a while coredump .

memory leaks? Process Stack Overflow? ...

during various tossing: GDB , modify the size of the coprocessor stack, Google , Consulting phper ...

soon to the evening, the search has been checked, the question has been asked, it is no way, stop to have a cup of tea: " call_user_function can you re-enter? " Think of this layer, I believe that understanding of the nature of the brothers and seconds understand: Your sister's, people realize Zend How to know the calling thread will also play the user-state scheduling Ah, this black box inside everything is possible ah! Global variables, static variables ...

Okay, get rid of it. Sendrecv This kind of extension based on the process, re-pressure measurement, single worker for 3w/s of the Echo It's easy and stress-free.

ending

Although this is the most attractive one Feature I didn't realize it at the end, but I was very happy because I once again confirmed one point: thinking tends to be more efficient than reckless . , especially when dealing with tricky problems, the headless fly-like disorderly collision often thankless, at this time, if you can calm down and try to collect the existing knowledge reserves, perhaps inspiration to patronize you.

possible directions for the future: PHP from 5.5 version introduces the yield , it feels like if you dig it out Zend for yield of support details, there might be hope and our C the frame is a good blend, but it always feels like a big hole to fill. If other factors aside, perhaps I would like to choose Golang a class of language directly enjoy The advantages of goroutine it, haha!

AppendixPHP extension Development and kernel applicationshttp://www.walu.cc/phpbook/preface.mdtwo ways to compile PHP extensionshttp://521-wf.com/archives/227.htmlHow to develop PHP extensions using C + + (top)http://521-wf.com/archives/241.htmlHow to develop PHP extensions using C + + (bottom)http://521-wf.com/archives/245.htmlWrapping C + + Classes in a PHP Extensionhttp://devzone.zend.com/1435/wrapping-c-classes-in-a-php-extension/

A failed PHP extension development

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.