php扩展中如何获取命令行参数,以及什么是SG

在思考zan框架如何解决热加载问题的时候,想着能不能每次也像fpm那样 rint,然后再调用php_execute_script执行,因为php_execute_script需要拿到php文件脚本的地址和参数,所以我遇到了如何在扩展内部获取命令行参数和脚本文件名,我们知道在php上次程序中可以直接调用$argv获取,那在扩展中如何拿到呢

我分析了sapi下的php_cli文件源码,发现参数是直接在 main(int argc, char *argv[])函数获取,然后在do_cli文件内复制给了SG 如下


  static int do_cli(int argc, char **argv) /* {{{ */
  {
        //....中间代码省略

    	SG(request_info).argc=argc-php_optind+1;
        arg_excp = argv+php_optind-1;
        arg_free = argv[php_optind-1];
        SG(request_info).path_translated = translated_path? translated_path: (char*)file_handle.filename;
        argv[php_optind-1] = (char*)file_handle.filename;
        SG(request_info).argv=argv+php_optind-1;

        //....
  }

昨天看php-fpm源码的时候 他会调用init_request_info(fcgi_request *request)函数也会对SG初始化赋值,代码就不贴了,所以参数都会在SG中,那SG到底是什么鬼玩意,其实他对应了一个结构体而已,看sapi.h的定义:

#ifdef ZTS
# define SG(v) ZEND_TSRMG(sapi_globals_id, sapi_globals_struct *, v)
SAPI_API extern int sapi_globals_id;
#else
# define SG(v) (sapi_globals.v)
extern SAPI_API sapi_globals_struct sapi_globals;    
#endif


typedef struct {
	const char *request_method;
	char *query_string;
	char *cookie_data;
	zend_long content_length;

	char *path_translated;
	char *request_uri;

	/* Do not use request_body directly, but the php://input stream wrapper instead */
	struct _php_stream *request_body;

	const char *content_type;

	zend_bool headers_only;
	zend_bool no_headers;
	zend_bool headers_read;

	sapi_post_entry *post_entry;

	char *content_type_dup;

	/* for HTTP authentication */
	char *auth_user;
	char *auth_password;
	char *auth_digest;

	/* this is necessary for the CGI SAPI module */
	char *argv0;

	char *current_user;
	int current_user_length;

	/* this is necessary for CLI module */
	int argc;
	char **argv;
	int proto_num;
} sapi_request_info;


typedef struct _sapi_globals_struct {
	void *server_context;
	sapi_request_info request_info;
	sapi_headers_struct sapi_headers;
	int64_t read_post_bytes;
	unsigned char post_read;
	unsigned char headers_sent;
	zend_stat_t global_stat;
	char *default_mimetype;
	char *default_charset;
	HashTable *rfc1867_uploaded_files;
	zend_long post_max_size;
	int options;
	zend_bool sapi_started;
	double global_request_time;
	HashTable known_post_content_types;
	zval callback_func;
	zend_fcall_info_cache fci_cache;
} sapi_globals_struct;

所以SG(request_info).argv 其实就是sapi_globals_struct结构体request_info下的argv字段

说了这么半天,那扩展中命令行参数到底怎么获取,明白上面原理就很简单啦 如下:

    char ** argv = SG(request_info).argv;
    printf("%s", argv[0]);
    printf("%s", argv[1]);
    printf("%s", argv[2]);

去试试看吧,另外如果你想获取 选项参数,类似与 php example.php -f “value for f” 要获取-f 和后面的值 在扩展中可以用,不过我没验证,我看到php_cli文件中是这么用的,扩展中应该也可以。

c = php_getopt(argc, argv, OPTIONS, &php_optarg, &php_optind, 0, 2)

发表评论

电子邮件地址不会被公开。 必填项已用*标注