字符串處理是我們常用的操作,而 zend 封裝了很多關於字符串操作相關的宏,先看下 ZVAL_STRING 和 ZVAL_STRINGL
#define ZVAL_STRING(z, s, duplicate) do { \
const char *__s=(s); \
zval *__z = (z); \
Z_STRLEN_P(__z) = strlen(__s); \
Z_STRVAL_P(__z) = (duplicate?estrndup(__s, Z_STRLEN_P(__z)):(char*)__s);\
Z_TYPE_P(__z) = IS_STRING; \
} while (0)
#define ZVAL_STRINGL(z, s, l, duplicate) do { \
const char *__s=(s); int __l=l; \
zval *__z = (z); \
Z_STRLEN_P(__z) = __l; \
Z_STRVAL_P(__z) = (duplicate?estrndup(__s, __l):(char*)__s);\
Z_TYPE_P(__z) = IS_STRING; \
} while (0)
因爲 php 內部很多字符串操作(例如 substr)最後都是給予這樣的宏來操作的,所以在這裏瞭解這兩個宏非常重要。
ZVAL_STRINGL 在處理的時候,因爲給了 length 參數,所以不需要在使用 strlen 來求字符串的長度了, 性能上有所提升。
關於 estrndup 也都是封裝了一層的,在 php 擴展開發的時候,儘量使用系統封裝的函數,這樣可以優化內存,降低內存泄漏等風險
ZEND_API char *_estrndup(const char *s, uint length ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
{
char *p;
#ifdef ZEND_SIGNALS
TSRMLS_FETCH();
#endif
HANDLE_BLOCK_INTERRUPTIONS();
p = (char *) _emalloc(length+1 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
if (UNEXPECTED(p == NULL)) {
HANDLE_UNBLOCK_INTERRUPTIONS();
return p;
}
memcpy(p, s, length);
p[length] = 0;
HANDLE_UNBLOCK_INTERRUPTIONS();
return p;
}
有幾個 e* 開發的函數 具體參看