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
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 whenphp_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
Johannes Schlueter wrote:
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 whenphp_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
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
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
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
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
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
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
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
I heard something similar; lazy bums the lot of 'em.
--Wez.
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
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.
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
Slackers that don't write their own books are the worst!
LOL, I couldnt agree more! :-D
Regards
Mark
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
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
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
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
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
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