Advanced Embedded
PHP's embedded ability can provide more than just synchronous loading and execution scripts. By understanding how various parts of the PHP execution module are grouped, even a script can be recalled to your host application. This chapter will cover the benefits of the I/O hooks provided by the SAPI layer and start learning from the executive module that you have obtained from the previous topics.
Callback to PHP
In addition to loading external scripts, and similar to what you saw in the previous chapter, your PHP embedded application will implement a command similar to User space eval ().
int zend_eval_string (char *str, Zval *retval_ptr,
char *string_name tsrmls_dc)
Here, str is the actual PHP script code to execute, and String_name is an arbitrary descriptive information associated with execution. If an error occurs, PHP will use this descriptive information as the "filename" in the error output. Retval_ptr, as you should have guessed, it will be set to the return value generated by the code being passed. Try the following code to create a new project.
#include <sapi/embed/php_embed.h>
int main (int argc, char *argv[]) {
php_embed_start_block (argc, argv)
zend_eval_string ("Echo ' Hello world! ';", NULL, "Simple Hello World App" tsrmls_cc);
Php_embed_end_block () return
0;
}
Now build it using either the command or the 19th "set hosting environment" (replace embed1 in makefile or command with EMBED2)
Alternatives: Inclusion of script files
Predictably, this makes it much easier to compile and execute external script files than before, because your application can replace the original complex open/ready/execute sequence of execution with this simplified but more powerful design alternative:
#include <sapi/embed/php_embed.h>
int main (int argc, char *argv[]) {
char *filename;
if (argc <= 1) {
fprintf (stderr, "Usage:%s <filename.php> <arguments>\n", argv[1]);
return-1;
}
FileName = argv[1];
/* Ignore the No. 0 parameter */
ARGC-;
argv + +;
Php_embed_start_block (argc, argv)
char *include_script;
spprintf (&include_script, 0, "include '%s ';", filename);
Zend_eval_string (Include_script, NULL, filename tsrmls_cc);
Efree (include_script);
Php_embed_end_block () return
0;
}
Note: This particular method must accept a disadvantage, if the file name contains single quotes, will cause parsing errors. However, this can be resolved by using the Php_addslashes () API call in Ext/standard/php_string.h. Take the time to read this file and the API references in the appendix, and you'll find a lot of features that will allow you to avoid reinventing the wheel later.
Calling User space functions
As you can see in the loading and executing script files, there are two ways to invoke user space functions internally. The most obvious possibility now is to reuse zend_eval_string (), organize the function name and all its parameters into a large string, and then collect the return value.
Php_embed_start_block (argc, argv)
char *command;
Zval retval;
spprintf (&command, 0, "nl2br ('%s ');", argv[1]);
Zend_eval_string (Command, &retval, "nl2br () execution" tsrmls_cc);
Efree (command);
printf ("Out:%s\n", Z_strval (retval));
Zval_dtor (&retval);
Php_embed_end_block ()
Like the previous include, this method has a fatal flaw: If the input parameter Paramin (argv[1 in the translator's example) gives an incorrect data, the function will fail or, worse, result in unexpected results. The solution is to always avoid the run-time fragment of the compiled code and invoke the function directly using the Call_user_function () API.
int call_user_function (HashTable *function_table, Zval **object_pp, Zval *function_name, Zval *retval_ptr
,
Zend_uint Param_count, Zval *params[] tsrmls_dc);