[PHP Extension] String

PHP 2010. 9. 14. 13:58



PHP Extension 제작시에는 일반적인 char* 에 malloc() 등으로 메모리를 할당하는 식의 문자열 관리는 불가하다.
(되긴 되는데 위험하다. 그냥 안된다고 생각하고 작업하는 것이 좋다.)
내부적으로 메모리 관리를 따로 하기 때문이다.

그래서 아래와 같은 방식으로 사용하는 것을 권장한다.
(emalloc, erealloc 등으로 할당하여 지저분하게 이어붙이는 것은 제외한다.)


spprintf()
PHP_FUNCTION(myext_test)
{
    int
test_int = 10;
    char *test_str = "ABCDE";

    char *str = NULL;
    spprintf(&str, 0, "%s%d", test_str, test_int);

    // "ABCDE10" 이라는 문자열을 반환
    ZVAL_STRING(return_value, str, 1);
    efree(str);

}

spprintf() 라는 것으로 할당하고, 마지막에는 해제해줘야 함.
하지만 spprintf() 는 대용량 문자열로 넘어가면 메모리 할당 에러 등의 문제가 발생한다.
(왜 그런지 내부적으로 까보지는 않았지만 그리된다...)

그래서 그냥 smart_str 을 이용하는 것을 권장한다.



smart_str
typedef struct {
    char *c;
    size_t len;
    size_t a;
} smart_str;


실제로 구조체는 ext/standard/php_smart_str_public.h 에 정의되어 있으나, (구조체만 정의되어 있다)
함수 등을 사용할 때는 ext/standard/php_smart_str.h를 include해서 사용한다.

smart_str의 사용예는 다음과 같다.

PHP_FUNCTION(myext_test)
{

    int
test_int = 10;
    char *test_str = "ABCDE";

    smart_str str = {0};

    // 정수 이어붙이기
    smart_str_append_long(&str, test_int);
    // 문자열 이어붙이기
    smart_str_appends(&str, test_str);
    // 문자열 종료시키기 (= 문자열 끝에 '\0' 붙이기)
    smart_str_0(&str);

    // "10ABCDE" 라는 문자열 반환
    ZVAL_STRING(return_value, str.c, 1);
    // smart_str 해제
    smart_str_free(&str);
}




다음은 smart_str을 이용한 sprintf() 식의 이어붙이기 함수이다.

static char *msprintf(const char *fmt, ...)
{
    smart_str str = {0};
    const char *p;
    int i;
    char *s;
    va_list argp;

    va_start(argp);

    for (p = fmt; *p!='\0'; p++) {
        if (*p!='%') {
            smart_str_appendc(&str, *p);
            continue;
        }

        switch (*++p) {
            case 'd':
                i = va_arg(argp, int);
                smart_str_append_long(&str, i);
                break;
            case 's':
                s = va_arg(argp, char*);
                smart_str_appends(&str, s);
                break;
            case '%':
                smart_str_appendc(&str, '%');
                break;
        }
    }
    va_end(argp);

    char *result = NULL;
    smart_str_0(&str);
    result = emalloc(str.len);
    strcpy(result, str.c);
    smart_str_free(&str);

    return result;
}

PHP_FUNCTION(myext_test)
{
    int t = 10;
    char *s = "ABCDE";

    char *result = msprintf("%d - %s<br>", t, s);
    ZVAL_STRING(return_value, result, 0);
    efree(result);
}

'PHP' 카테고리의 다른 글

[PHP] 소스에서 추출한 에러메세지  (0) 2010.10.13
[PHP Extension] 잡다한 것들.  (6) 2010.09.14
[PHP] mod_php5 request life cycle  (0) 2010.09.14
[PHP] PHP Core - PHP interpreter  (0) 2010.09.14
[PHP] mod_php5 (SAPI for Apache)  (0) 2010.09.14
Posted by bloodguy
,