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" <[EMAIL PROTECTED]>
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



--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to