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





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);   
}




test.php
var_dump(myext_get_count());
myext_increase_count();
myext_increase_count();
var_dump(myext_get_count());


위와 같이 호출하면 호출할 때마다 전역변수 값이 2씩 증가한 채로 유지되는 것을 확인할 수 있음.
다만 주의해야 할 것은,
MINIT가 프로세스별로 초기화를 해버리므로 브라우저에서 호출할 때 각자 다른 아파치의 프로세스가 연결되면,
값은 그대로 유지되지 않는다.




Posted by bloodguy
,