# PHP Embedded

- Thread: https://externals.io/message/22425
- Original archive: https://news-web.php.net/php.internals/22425
- Started by Marco on 2006-03-14T19:48:09+00:00
- Messages: 19
- Reply by email to internals@lists.php.net
- More for agents: search with https://externals.io/search.md?q={query} · JSON API at https://externals.io/api · documentation at https://externals.io/llms.txt

---

## #22425 — Marco — 2006-03-14T19:48:09+00:00

URL: https://externals.io/message/22425#22425

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

---

## #22428 — Johannes Schlueter — 2006-03-14T20:58:25+00:00

URL: https://externals.io/message/22425#22428 · In reply to: #22425

Hi Mark,


> 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

---

## #22429 — George Schlossnagle — 2006-03-14T21:10:33+00:00

URL: https://externals.io/message/22425#22429 · In reply to: #22428

Johannes Schlueter wrote:

>Hi Mark,
>
>
>  
>
> > […]
>
>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.
>
>  
>
> > […]
>
>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

---

## #22430 — Mark Evans — 2006-03-14T21:21:17+00:00

URL: https://externals.io/message/22425#22430 · In reply to: #22428

> 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

---

## #22431 — Mark Evans — 2006-03-14T21:22:11+00:00

URL: https://externals.io/message/22425#22431 · In reply to: #22429

> 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

---

## #22435 — Mark Evans — 2006-03-15T00:12:00+00:00

URL: https://externals.io/message/22425#22435 · In reply to: #22428

> 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

---

## #22436 — Mark Evans — 2006-03-15T00:21:33+00:00

URL: https://externals.io/message/22425#22436 · In reply to: #22435

> 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

---

## #22437 — Andrey Hristov — 2006-03-15T00:32:10+00:00

URL: https://externals.io/message/22425#22437 · In reply to: #22436

Mark Evans wrote:
> > […]
> 
> 
> 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

---

## #22438 — Sara Golemon — 2006-03-15T01:10:35+00:00

URL: https://externals.io/message/22425#22438 · In reply to: #22437

> > […]
>   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).

> > […]
>
Nah, reading is overrated, just so long as you buy it ;)

-Sara

---

## #22440 — George Schlossnagle — 2006-03-15T02:04:11+00:00

URL: https://externals.io/message/22425#22440 · In reply to: #22438

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

---

## #22443 — Wez Furlong — 2006-03-15T02:55:10+00:00

URL: https://externals.io/message/22425#22443 · In reply to: #22440

I heard something similar; lazy bums the lot of 'em.

--Wez.


> Sara Golemon wrote:
>
> > […]
>
> I heard it was because those guys were total slackers.
>
> George

---

## #22444 — Rasmus Lerdorf — 2006-03-15T03:54:04+00:00

URL: https://externals.io/message/22425#22444 · In reply to: #22443

Slackers that don't write their own books are the worst!

Wez Furlong wrote:
> I heard something similar; lazy bums the lot of 'em.
> 
> --Wez.
> 
> 
> > […]

---

## #22445 — Michael Vergoz — 2006-03-15T06:38:07+00:00

URL: https://externals.io/message/22425#22445 · In reply to: #22425

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

---

## #22446 — Mark Evans — 2006-03-15T06:52:06+00:00

URL: https://externals.io/message/22425#22446 · In reply to: #22438

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 :-)

> > […]
> 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

---

## #22447 — Mark Evans — 2006-03-15T06:53:04+00:00

URL: https://externals.io/message/22425#22447 · In reply to: #22444

> Slackers that don't write their own books are the worst!

LOL, I couldnt agree more! :-D

Regards

Mark

---

## #22451 — Mark Evans — 2006-03-15T08:17:27+00:00

URL: https://externals.io/message/22425#22451 · In reply to: #22445

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

---

## #22482 — Mark Evans — 2006-03-16T12:34:09+00:00

URL: https://externals.io/message/22425#22482 · In reply to: #22428

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

---

## #22484 — Michael Vergoz — 2006-03-16T14:14:08+00:00

URL: https://externals.io/message/22425#22484 · In reply to: #22482

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 :-)
>
> > […]
>
> 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()
> > […]
> 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

---

## #22485 — Mark Evans — 2006-03-16T14:25:24+00:00

URL: https://externals.io/message/22425#22485 · In reply to: #22484

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
