通过嵌入包装重新创建cli

现在php已经可以在你的应用中访问了, 是时候让它做⼀些事情了. 本章剩下的核心就是围绕着在这个测试应用框架中重新创建cli sapi展开的.

很简单, cli二进制程序最基础的功能就是在命令行指定⼀个脚本的名字, 由php对其解 释执行. 用下面的代码替换你的embed1.c的内容就在你的应用中实现了cli.

  1. #include <stdio.h>
  2. #include <sapi/embed/php_embed.h>
  3. int main(int argc, char *argv[]) {
  4. zend_file_handle script;
  5. /* 基本的参数检查 */ if ( argc <= 1 ) {
  6. fprintf(stderr, "Usage: %s <filename.php> <arguments>\n", argv[0]);
  7. return -1; }
  8. /* 设置⼀一个文件处理结构 */
  9. script.type
  10. script.filename
  11. script.opened_path
  12. script.free_filename
  13. if ( !(script.handle.fp = fopen(script.filename, "rb")) ) {
  14. fprintf(stderr, "Unable to open: %s\n", argv[1]);
  15. return -1; }
  16. /* 在将命令行参数注册给php时(php中的$argv/$argc), 忽略第一个命令行参数, 因为它对php脚本无意义 */
  17. argc --;
  18. argv ++;
  19. PHP_EMBED_START_BLOCK(argc, argv)
  20. php_execute_script(&script TSRMLS_CC);
  21. PHP_EMBED_END_BLOCK()
  22. return 0; }
  23. 译注: 原著中的代码在译者的环境不能直接运行, 上面的代码是经过修改的.

当然, 你需要⼀个文件测试它, 创建⼀个小的php脚本, 命名为test.php, 在命令行使用你的embed程序执行它:

  1. $ ./embed1 test.php

如果你给命令行传递了其他参数, 你可以在你的php脚本中使用$_SERVER[‘argc’]/ $_SERVER[‘argv’]看到它们.

你可能注意到了, 在PHP_EMBED_START_BLOCK()和PHP_EMBED_END_BLOCK()之间 的代码是缩进的. 这个细节是因为这两个宏实际上构成了⼀个C语言的代码块作用域. 也就是说 PHP_EMBED_START_BLOCK()包含⼀个打开的花括号”{“, 在PHP_EMBED_END_BLOCK()中 则有与之对应的关闭花括号”}”. 这样做非常重要的一个问题是它们不能被放入到独立的启动/终止函数中. 下一章你将看到这个问题的解决方案.