Re: PHP Embedded

From: Date: Thu, 16 Mar 2006 14:14:08 +0000
Subject: Re: PHP Embedded
References: 1 2 3  Groups: php.internals 
Request: Send a blank email to internals+get-22484@lists.php.net to get a copy of this message
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
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 -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php


« previous php.internals (#22484) next »