PHP Embedded

php.internals

Mark Evans

20 years ago
Hi All The company I am doing some work for is currently using the php_embed to access the php engine from within a windows based c++ application. I have been asked a question that I dont know the answer to and all my googling attempts have failed. Is there a way from within the embedded system to destroy all created variables so that the environment is the same as when it was started or do we need to shutdown the embedded engine and start it up again? Also a problem they are coming up with occasionally is that the php engine will crash when php_embed_init(argc, argv PTSRMLS_CC); is called, they havent found any reproducible steps yet. Could this be caused by shutting down and starting up the emdedded engine from within the same app? I have asked and the application isnt multi threaded. Finally is there any examples of how to embed php in a windows app? I have done some googling and have found odd code snippets but if there is a detailed doc I could read I would be most grateful. Thanks in advance for any information provided. Regards Mark

Johannes Schlueter

20 years ago
Hi Mark, On Tuesday 14 March 2006 20:48, Marco wrote:
> Is there a way from within the embedded system to destroy all created > variables so that the environment is the same as when it was started or do > we need to shutdown the embedded engine and start it up again?
PHP was designed as an language running as an module inside an webserver to run multiple, independent, request, one after each other. So PHP supports reinitilizing the engine without restarting everything. Look around for php_request_startup() and php_request_shutdown() and how they are used.
> Also a problem they are coming up with occasionally is that the php engine > will crash when > > php_embed_init(argc, argv PTSRMLS_CC); > > is called, they havent found any reproducible steps yet. Could this be > caused by shutting down and starting up the emdedded engine from within the > same app? I have asked and the application isnt multi threaded.
Here one can't say much without any details (_relevant_ code and backtrace) php_embed_* are afaik wrapping up the complete engine und request init and shutdown. If you want to do multiple independent requests you should take an a bit closer look on the SAPI layer to use the functions I mentioned above.
> Finally is there any examples of how to embed php in a windows app? I have > done some googling and have found odd code snippets but if there is a > detailed doc I could read I would be most grateful. > > Thanks in advance for any information provided.
There are quite a few "embedding PHP in an application"-examples in php-src/sapi. If you don't like reading that code wait some weeks and you might get Sara Golemon's not yet released book (ISBN: 067232704X) about "Extending and Embedding PHP" if that's to late you might want to fetch George Schlossnagle's (ISBN: 0672325616) which is anyways a good read about "Advanced PHP Programming" and has a few chapters about PHP internals like the SAPI layer. johanne

George Schlossnagle

20 years ago
Johannes Schlueter wrote:
>Hi Mark, > >On Tuesday 14 March 2006 20:48, Marco wrote: > > >>Is there a way from within the embedded system to destroy all created >>variables so that the environment is the same as when it was started or do >>we need to shutdown the embedded engine and start it up again? >> >> > >PHP was designed as an language running as an module inside an webserver to >run multiple, independent, request, one after each other. So PHP supports >reinitilizing the engine without restarting everything. Look around for >php_request_startup() and php_request_shutdown() and how they are used. > > > >>Also a problem they are coming up with occasionally is that the php engine >>will crash when >> >>php_embed_init(argc, argv PTSRMLS_CC); >> >>is called, they havent found any reproducible steps yet. Could this be >>caused by shutting down and starting up the emdedded engine from within the >>same app? I have asked and the application isnt multi threaded. >> >> > >Here one can't say much without any details (_relevant_ code and backtrace) > >php_embed_* are afaik wrapping up the complete engine und request init and >shutdown. If you want to do multiple independent requests you should take an >a bit closer look on the SAPI layer to use the functions I mentioned above. > >
If you want an example of doing request startup/shutdown multithreaded with the embed SAPI and are willing to wade through a bit of XS, you can check out the PHP::Interpreter Perl module (on CPAN: http://search.cpan.org/dist/PHP-Interpreter/). That links against the embed SAPI but uses the native engine calls for handling request mortality. You could also check out Sara's runkit in PECL, I think that does similar stuff. George

Mark Evans

20 years ago
> If you want an example of doing request startup/shutdown multithreaded > with the embed SAPI and are willing to wade through a bit of XS, you can > check out the PHP::Interpreter Perl module (on CPAN: > http://search.cpan.org/dist/PHP-Interpreter/). That links against the > embed SAPI but uses the native engine calls for handling request > mortality. You could also check out Sara's runkit in PECL, I think that > does similar stuff.
Great thankyou, I will certainly take a look at both of these to see what we are doing wrong. Regards Mark

Mark Evans

20 years ago
> Here one can't say much without any details (_relevant_ code and backtrace) > > php_embed_* are afaik wrapping up the complete engine und request init and > shutdown. If you want to do multiple independent requests you should take an > a bit closer look on the SAPI layer to use the functions I mentioned above.
I thought that would be the case, thanks for the info provided, I will pass that on to our c++ guys.
> There are quite a few "embedding PHP in an application"-examples in > php-src/sapi. If you don't like reading that code wait some weeks and you > might get Sara Golemon's not yet released book (ISBN: 067232704X) about > "Extending and Embedding PHP" if that's to late you might want to fetch > George Schlossnagle's (ISBN: 0672325616) which is anyways a good read about > "Advanced PHP Programming" and has a few chapters about PHP internals like > the SAPI layer.
Thanks, those books sound interesting, I guess I will buy both since you can never have enough reference material IMO. Thanks for your time. Regards Mark

Mark Evans

20 years ago
> you might get Sara Golemon's not yet released book (ISBN: 067232704X) about > "Extending and Embedding PHP"
I just did a search on Amazon for the above ISBN and it returned a book as follows Extending and Embedding PHP - Wez Furlong, George Schlossnagle Paperback 448 pages (March 2005) Publisher: Sams Language: English ISBN: 067232704X Is this the right book as it has a publish date of March 2005. Regards Mark

Mark Evans

20 years ago
> Is this the right book as it has a publish date of March 2005.
Hmm, it seems that amazon.co.uk are confused :-) Searching amazon.com gives me Extending and Embedding PHP (Paperback) by Sara Golemon * Paperback: 448 pages * Publisher: Sams (May 24, 2006) * Language: English * ISBN: 067232704X I have placed an order for this book, I guess I should try and finish reading the other 4 php books I purchased recently before then :-) Regards Mark

Andrey Hristov

20 years ago
Mark Evans wrote:
>> Is this the right book as it has a publish date of March 2005. > > > Hmm, it seems that amazon.co.uk are confused :-) > > Searching amazon.com gives me > > Extending and Embedding PHP (Paperback) > by Sara Golemon > > * Paperback: 448 pages > * Publisher: Sams (May 24, 2006) > * Language: English > * ISBN: 067232704X > > I have placed an order for this book, I guess I should try and finish > reading the other 4 php books I purchased recently before then :-) > > Regards > > Mark >
it's pretty strange. at amazon.com the book is listed with author pollita, but on the cover Wez and George are mentioned. Go figure.. :) Andrey

Sara Golemon

20 years ago
> > > Is this the right book as it has a publish date of March 2005. > > > > Extending and Embedding PHP (Paperback) > > by Sara Golemon > > > > * Paperback: 448 pages > > * Publisher: Sams (May 24, 2006) > > * Language: English > > * ISBN: 067232704X > > > it's pretty strange. at amazon.com the book is listed with author
pollita,
> but on the cover Wez and George are mentioned. Go figure.. :) >
Originally George and Wez were going to be writing this book (and may yet do their own version -- that's up to them). Due to innocuous reasons that I can probably talk about but won't to be on the safe side, I wound up taking over the project (and the ISBN number along with it). www.amazon.com has the updated metadata, some (most?) other pre-sellers don't. Bottom line. If you order that ISBN numbered book, you'll get mine. The tricks of using php_request_startup()/php_request_shutdown() aren't covered (the embedding section focuses on some of the simpler uses of sapi/embed, the title would be way too long if I covered everything you could do in every part of the interpreter). The short answer is: call php_request_shutdown(NULL); to kill the active interpreter (one is started implicitly by PHP_EMBED_START_BLOCK(), then php_request_startup(TSRMLS_C); to initialize a new one (the last one active at PHP_EMBED_END_BLOCK() will be impliticly shutdown).
> > I have placed an order for this book, I guess I should try and finish > > reading the other 4 php books I purchased recently before then :-) > > >
Nah, reading is overrated, just so long as you buy it ;) -Sara

George Schlossnagle

20 years ago
Sara Golemon wrote:
> >Originally George and Wez were going to be writing this book (and may yet do >their own version -- that's up to them). Due to innocuous reasons that I >can probably talk about but won't to be on the safe side, I wound up taking >over the project (and the ISBN number along with it). >
I heard it was because those guys were total slackers. George

Wez Furlong

20 years ago
I heard something similar; lazy bums the lot of 'em. --Wez. On 3/14/06, George Schlossnagle <george@omniti.com> wrote:

Rasmus Lerdorf

20 years ago
Slackers that don't write their own books are the worst! Wez Furlong wrote:

Mark Evans

20 years ago
> Slackers that don't write their own books are the worst!
LOL, I couldnt agree more! :-D Regards Mark

Mark Evans

20 years ago
Hi Sara
> The short answer is: call php_request_shutdown(NULL); to kill the active > interpreter (one is started implicitly by PHP_EMBED_START_BLOCK(), then > php_request_startup(TSRMLS_C); to initialize a new one (the last one active > at PHP_EMBED_END_BLOCK() will be impliticly shutdown).
Great many thanks, this seemed to be easier than I thought :-)
>>> I have placed an order for this book, I guess I should try and finish >>> reading the other 4 php books I purchased recently before then :-) >>> > Nah, reading is overrated, just so long as you buy it ;)
LOL, I hope you enjoy writing the book, I did a technical review of a PHP 5 ecommerce book a while ago which was a lot of work, so I can imagine how much more work must be involved to actually write the thing. Regards Mark

Mark Evans

20 years ago
Hi All I am back again :-)
> Here one can't say much without any details (_relevant_ code and > backtrace)
The c++ guys are still having some problems and they have given me some more info.. The app is init'd using the following __declspec(dllexport) void InitPHPEngine(const CString& sStartupDir) { static bool bInitialised = false; if (!bInitialised) { int argc = 1; char *argv[2] = {"Actinic", NULL}; php_embed_module.ub_write = ub_write; // output is redirected to our callback function php_embed_module.log_message = log_message; php_embed_module.sapi_error = sapi_error; php_embed_module.php_ini_path_override = ".\\"; php_embed_init(argc, argv PTSRMLS_CC); // init the engine CString sInit = PHP_INIT_SCRIPT; if (!sStartupDir.IsEmpty()) // if startup dir is defined { CString sPath; sPath.Format("chdir(\"%s\");", CTextUtils::MakeStringSafeForQuotedPerlFragment(sStartupDir)); sInit += sPath; } zend_eval_string(sInit.GetBuffer(), NULL, "main" TSRMLS_CC); bInitialised = true; } } They then have a method BOOL PHPEvalString(const CString& sCode, zval *pzvalResult, bool bExpression) { CString sPreparedCode; if (bExpression) // we should apply a trick for expressions { sPreparedCode.Format(_T("%s ? true : false"), sCode); } else { sPreparedCode = sCode; gsPhpOutput.Empty(); gsPhpOutput.GetBuffer(sCode.GetLength()); // preallocate the string - hopefully the result has similar length as the original script, so probably that's a good guess gsPhpOutput.ReleaseBuffer(); // doesn't release the extra bytes } char* pcScript = sPreparedCode.GetBuffer(sPreparedCode.GetLength()); zend_first_try { PG(during_request_startup) = 0; int nResult; if (bExpression) { nResult = zend_eval_string(pcScript, pzvalResult, "main" TSRMLS_CC); } else { nResult = zend_eval_string(pcScript, NULL, "main" TSRMLS_CC); } if (nResult == FAILURE) { return FALSE; } } zend_catch { return FALSE; } zend_end_try(); return TRUE; } Therefore they want to shut down the request after the line nResult = zend_eval_string(pcScript, NULL, "main" TSRMLS_CC); and restart it for the next call But doing nResult = zend_eval_string(pcScript, NULL, "main" TSRMLS_CC); TSRMLS_FETCH(); php_request_shutdown(NULL); php_request_startup(TSRMLS_C); Causes an immediate crash when it reaches php_request_startup(TSRMLS_C); :( Also because init, eval and shutdown are in separate functions tsrm_ls is defined as static in the app. The also sent me the following backtrace if its of any use.. php4ts.dll!00d45b61() php4ts.dll!00d45622() user32.dll!77d6ebe2() php4ts.dll!00d43e16()
> ActPHPRunner.dll!PHPEvalString(const
ATL::CStringT<char,StrTraitMFC_DLL<char,ATL::ChTraitsCRT<char> > > & sCode={...}, _zval_struct * pzvalResult=0x0012e558, bool bExpression=false) Line 372 + 0x7c C++ Any advice is greatly appreciated. Regards Mark

Michael Vergoz

20 years ago
Hi, You should understand that the current php_embed code isn't ready to be runned within any type of context (C context or C++ object context). It is just a ONE Shot execution. Have a look at : http://cvs.php.net/viewcvs.cgi/php-src/sapi/embed/php_embed.c?view=markup&rev=1.1.2.5.2.1 You can see that the request is destroyed at the shutdown time (should be your class destructor). void php_embed_shutdown(TSRMLS_D) { php_request_shutdown((void *) 0); [..] } That why i have develop a different way to allow you (for example) to keep a PHP context within an Object. http://www.badcode.be/~descript/PHP/php_embed/ To install it you just have to replace php_embed.c & php_embed.h from your sapi/embed/ . Now i give to you an example : class MyObject { public: MyObject() { this->ctx = php_embed_ctx_init(); php_embed_ctx_set_var( this->ctx, PHP_EMBED_VKEY("MyObject"), this ); }; public: ~MyObject() { php_embed_ctx_fini(this->ctx); }; public: execute(char *code) { php_embed_ctx_execute(this->ctx, code); }; private: php_embed_ctx *ctx; } php_embed_ret my_stdout(php_embed_ctx *ctx, const char *str, uint str_l) { MyObject **obj; PHP_EMBED_LOAD_VKEY_FROM(ctx, obj, "MyObject"); // your object is here // (*obj)->something return(PHP_EMBED_HOOK); } There is other useful possiblity but actualy you'll need to look my comments at http://www.badcode.be/~descript/PHP/php_embed/php_embed.h I don't have many time to make more documentation. And you must to know that this modification isn't official so i don't have motivation to continue. /* API */ php_embed_ctx *php_embed_ctx_init(); int php_embed_ctx_fini(php_embed_ctx *); int php_embed_ctx_execute(php_embed_ctx *, char *); int php_embed_ctx_add_funcs(php_embed_ctx *, zend_function_entry *); int php_embed_ctx_set_var(php_embed_ctx *, char *, uint, void *); int php_embed_ctx_unset_var(php_embed_ctx *, char *, uint); void *php_embed_ctx_find_var(php_embed_ctx *, char *, uint); /* standard output */ int php_embed_ctx_set_stdout( php_embed_ctx *, void * ); int php_embed_ctx_unset_stdout(php_embed_ctx *); /* flush */ int php_embed_ctx_set_flush( php_embed_ctx *, void * ); int php_embed_ctx_unset_flush(php_embed_ctx *); /* log output */ int php_embed_ctx_set_log( php_embed_ctx *, void * ); int php_embed_ctx_unset_log(php_embed_ctx *); Michael Vergoz ----- Original Message ----- From: "Mark Evans" <markright@gmail.com> To: <internals@lists.php.net> Sent: Thursday, March 16, 2006 1:34 PM Subject: Re: [PHP-DEV] PHP Embedded

Mark Evans

20 years ago
Michael Vergoz wrote:
> There is other useful possiblity but actualy you'll need to look my > comments at http://www.badcode.be/~descript/PHP/php_embed/php_embed.h > I don't have many time to make more documentation. And you must to know > that this modification isn't official so i don't have motivation to > continue.
Thanks Michael, I have passed this onto the c++ developer. Regards Mark

Michael Vergoz

20 years ago
Hello, I have made an unaccepted php_embed extension available at http://www.badcode.be/~descript/PHP/php_embed/ Take a look at the example : http://www.badcode.be/~descript/PHP/php_embed/examples/pembed_new.c I use this part of code on my software with C++ If you have questions ... Michael ----- Original Message ----- From: "Marco" <markright@gmail.com> To: <internals@lists.php.net> Sent: Tuesday, March 14, 2006 8:48 PM Subject: [PHP-DEV] PHP Embedded Hi All The company I am doing some work for is currently using the php_embed to access the php engine from within a windows based c++ application. I have been asked a question that I dont know the answer to and all my googling attempts have failed. Is there a way from within the embedded system to destroy all created variables so that the environment is the same as when it was started or do we need to shutdown the embedded engine and start it up again? Also a problem they are coming up with occasionally is that the php engine will crash when php_embed_init(argc, argv PTSRMLS_CC); is called, they havent found any reproducible steps yet. Could this be caused by shutting down and starting up the emdedded engine from within the same app? I have asked and the application isnt multi threaded. Finally is there any examples of how to embed php in a windows app? I have done some googling and have found odd code snippets but if there is a detailed doc I could read I would be most grateful. Thanks in advance for any information provided. Regards Mark

Mark Evans

20 years ago
HI Michael
> I have made an unaccepted php_embed extension available at > http://www.badcode.be/~descript/PHP/php_embed/ > Take a look at the example : > http://www.badcode.be/~descript/PHP/php_embed/examples/pembed_new.c > I use this part of code on my software with C++ > If you have questions ...
Great many thanks, I think I am finally starting to understand how this all works.. Look out world... c++ newbie coming through :-D Regards Mark