PHP Extension에서 전역변수를 써야할 때가 있을 것이다.
하지만 Thread Safety를 고려해야지 그냥 막 선언해서 쓰면 안된다.
전역변수를 선언하고 사용하는 매크로가 친절하게 준비되어 있다.
아래는 long 형 전역변수를 선언하고 계속 값을 증가시킬 수 있는 예제.
MINIT, RINIT 모두 초기화할 수 있는 타이밍이므로 쓰임새에 맞게 초기화하면 됨.
stdafx.h 는 생략.
php_myext.h
#ifndef PHP_MYEXT_H
#define PHP_MYEXT_H 1
#define PHP_MYEXT_VERSION "1.0"
#define PHP_MYEXT_EXTNAME "myext"
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
// Thread Safe Resource Manager
extern "C" {
#ifdef ZTS
#include "TSRM.h"
#endif
}
// extension global 선언 매크로
ZEND_BEGIN_MODULE_GLOBALS(myext)
long myext_counter_value;
ZEND_END_MODULE_GLOBALS(myext)
// 전역변수 뽑아먹는 매크로
#ifdef ZTS
#define MYEXT_G(v) TSRMG(myext_globals_id, zend_myext_globals *, v)
#else
#define MYEXT_G(v) (myext_globals.v)
#endif
// init 함수선언
PHP_MINIT_FUNCTION(myext);
PHP_RINIT_FUNCTION(myext);
// user space function export
PHP_FUNCTION(myext_get_count);
PHP_FUNCTION(myext_increase_count);
extern zend_module_entry myext_module_entry;
#define phpext_myext_ptr &myext_module_entry;
#endif
#define PHP_MYEXT_H 1
#define PHP_MYEXT_VERSION "1.0"
#define PHP_MYEXT_EXTNAME "myext"
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
// Thread Safe Resource Manager
extern "C" {
#ifdef ZTS
#include "TSRM.h"
#endif
}
// extension global 선언 매크로
ZEND_BEGIN_MODULE_GLOBALS(myext)
long myext_counter_value;
ZEND_END_MODULE_GLOBALS(myext)
// 전역변수 뽑아먹는 매크로
#ifdef ZTS
#define MYEXT_G(v) TSRMG(myext_globals_id, zend_myext_globals *, v)
#else
#define MYEXT_G(v) (myext_globals.v)
#endif
// init 함수선언
PHP_MINIT_FUNCTION(myext);
PHP_RINIT_FUNCTION(myext);
// user space function export
PHP_FUNCTION(myext_get_count);
PHP_FUNCTION(myext_increase_count);
extern zend_module_entry myext_module_entry;
#define phpext_myext_ptr &myext_module_entry;
#endif
myext.cpp
#include "stdafx.h"
// global 선언 매크로
ZEND_DECLARE_MODULE_GLOBALS(myext)
// get, set 함수리스트
static function_entry myext_functions[] = {
PHP_FE(myext_get_count, NULL)
PHP_FE(myext_increase_count, NULL)
{NULL, NULL, NULL}
};
zend_module_entry myext_module_entry = {
#if ZEND_MODULE_API_NO >= 20010901
STANDARD_MODULE_HEADER,
#endif
PHP_MYEXT_EXTNAME,
myext_functions,
PHP_MINIT(myext),
NULL,
PHP_RINIT(myext),
NULL,
NULL,
#if ZEND_MODULE_API_NO >= 20010901
PHP_MYEXT_VERSION,
#endif
STANDARD_MODULE_PROPERTIES
};
extern "C" {
ZEND_GET_MODULE(myext)
}
// MINIT에서 초기화할 수 있는 callback
static void php_myext_globals_ctor(zend_myext_globals *myext_globals TSRMLS_DC)
{
MYEXT_G(myext_counter_value) = 0;
}
PHP_MINIT_FUNCTION(myext)
{
// args1: extension 이름
// args2: 전역변수를 초기화 할 수 있는 콜백함수
// args3: 전역변수를 해제할 수 있는 콜백함수
ZEND_INIT_MODULE_GLOBALS(myext, php_myext_globals_ctor, NULL);
return SUCCESS;
}
PHP_RINIT_FUNCTION(myext)
{
MYEXT_G(myext_counter_value) = 0;
return SUCCESS;
}
// get
PHP_FUNCTION(myext_get_count)
{
RETURN_LONG(MYEXT_G(myext_counter_value));
}
// increase
PHP_FUNCTION(myext_set_count)
{
++MYEXT_G(myext_counter_value);
}
// global 선언 매크로
ZEND_DECLARE_MODULE_GLOBALS(myext)
// get, set 함수리스트
static function_entry myext_functions[] = {
PHP_FE(myext_get_count, NULL)
PHP_FE(myext_increase_count, NULL)
{NULL, NULL, NULL}
};
zend_module_entry myext_module_entry = {
#if ZEND_MODULE_API_NO >= 20010901
STANDARD_MODULE_HEADER,
#endif
PHP_MYEXT_EXTNAME,
myext_functions,
PHP_MINIT(myext),
NULL,
PHP_RINIT(myext),
NULL,
NULL,
#if ZEND_MODULE_API_NO >= 20010901
PHP_MYEXT_VERSION,
#endif
STANDARD_MODULE_PROPERTIES
};
extern "C" {
ZEND_GET_MODULE(myext)
}
// MINIT에서 초기화할 수 있는 callback
static void php_myext_globals_ctor(zend_myext_globals *myext_globals TSRMLS_DC)
{
MYEXT_G(myext_counter_value) = 0;
}
PHP_MINIT_FUNCTION(myext)
{
// args1: extension 이름
// args2: 전역변수를 초기화 할 수 있는 콜백함수
// args3: 전역변수를 해제할 수 있는 콜백함수
ZEND_INIT_MODULE_GLOBALS(myext, php_myext_globals_ctor, NULL);
return SUCCESS;
}
PHP_RINIT_FUNCTION(myext)
{
MYEXT_G(myext_counter_value) = 0;
return SUCCESS;
}
// get
PHP_FUNCTION(myext_get_count)
{
RETURN_LONG(MYEXT_G(myext_counter_value));
}
// increase
PHP_FUNCTION(myext_set_count)
{
++MYEXT_G(myext_counter_value);
}
test.php
var_dump(myext_get_count());
myext_increase_count();
myext_increase_count();
var_dump(myext_get_count());
myext_increase_count();
myext_increase_count();
var_dump(myext_get_count());
위와 같이 호출하면 호출할 때마다 전역변수 값이 2씩 증가한 채로 유지되는 것을 확인할 수 있음.
다만 주의해야 할 것은,
MINIT가 프로세스별로 초기화를 해버리므로 브라우저에서 호출할 때 각자 다른 아파치의 프로세스가 연결되면,
값은 그대로 유지되지 않는다.
'PHP' 카테고리의 다른 글
[PHP Extension] INI 세팅 (0) | 2010.08.04 |
---|---|
[PHP Extension] Auto Globals (0) | 2010.08.04 |
[PHP Extension] 상수 (Constants) (0) | 2010.08.04 |
[PHP Extension] phpinfo() 에 extension 정보 출력하기 (0) | 2010.08.04 |
[PHP Extension] Data types used by Zend/PHP (0) | 2010.08.02 |