PHP Extensions: Introduction to data types

10 May

zval is the fundamental type of data storage in zend. It’s a small struct having four member defined in Zend/zend.h

The format of the structure is

typedef struct _zval_struct {

zvalue_value value;

zend_uint refcount;

zend_uchar type;

zend_uchar is_ref;

}zval;

Here refcount is of type unsigned int.

type and is_ref are both unsigned char.

However value is union structure. And has format as

typedef union _zvalue_value {

long lval;

double dval;

struct {

char *val;

int len;

}

HashTable *ht;

zend_object_value obj;

}zvalue_value;

Zend has currently eight data type.

  1. IS_BOOL: can contain true or false.
  2. IS_LONG : used for integer data.
  3. IS_DOUBLE: for floating point numbers.
  4. IS_STRING: for character data.
  5. IS_ARRAY: for consecutive value. This can contain complex set of data buckets.
  6. IS_OBJECT: it take array one level forward by specify access modifiers, methods, and special events.
  7. IS_RESOURCE: values or pointer that cannot be handle through scalar array values, then this type is used.

Another important thing is

IS_NULL: used to check whether or not the variable contain value.

Data values

As all the variable in the zend can be represented by zval. We can inspect zval through several macros.

If we have

zval val;

we can check its type as

Z_TYPE(val);

An example could be

if (Z_TYPE(val) == IS_BOOL) {

// bool value.

} else if(Z_TYPE(val) == IS_LONG) {

// integer value

}

If we have a pointer, pointing to specific value, then the macro Z_TYPE changes to Z_TYPE_P.

Consider the following example

zval *val;

Z_TYPE_P(val);

And the example above become.

if(Z_TYPE_P(val) == IS_BOOL) {

// bool value.

} else if(Z_TYPE_P(val) == IS_LONG) {

// integer value

}

And the scenario changed more, when we have pointer to pointer.

Like

zval **val;

Z_TYPE_P(val);

And the example above become.

if(Z_TYPE_PP(val) == IS_BOOL) {

// bool value.

} else if(Z_TYPE_PP(val) == IS_LONG) {

// integer value

}

Strings are handle more differently. For example if you want to print an integer value, write

printf(“%d”,val);

Well, for extension development it would be better to use another very brilliant method called php_printf();

you can use it like

php_printf(“%d”,val);

However from the above union structure, we can see that string has two attribute, strval, and strlen.

To print the string, use another function

PHPWRITE(Z_STRVAL_P(val), Z_STRLEN_P(val));

Data Creation

Creating variable need to have a memory allocated to it in the storage media. In c memory is allocated using different function like

malloc(sizeof(int))

However this will not be a good choice to use while building extensions.

Use another macro provided

MAKE_STD_ZVAL(zv);

This macro declares the variable but didn’t initialize a value. If you want your variable to be declared and initialized, use another macro.

ALLOC_INIT_ZVAL(zv);

This declare the a variable zv and assigned it IS_NULL;

In addition to these, zend exposed yet another macros for handing zval.

ZVAL_NULL(zv);

ZVAL_TRUE(zv);

ZVAL_FALSE(zv);

Another approach can also be used.

Z_TYPE_P(zv) = IS_LONG;

Z_LVAL_P(zv) = 42;

ZVAL_BOOL(zv, 1)

ZVAL_BOOL(zv, 0);

Or you can define as

Z_TYPE_P(zv) = IS_BOOL;

Z_LVAL_P(zv) = 42;

For string, this takes a bit more

Z_TYPE_P(zv) = IS_STRING;

Z_STRLEN_P(zv) = len;

Z_STRVAL = val;

Data Storage

When a variable is declared in uperspace, zend store it in symbol table, the global symbol table is created at the time of request initialization before the function in the RINIT functions are called and deleted at the time of resource shutdown.

Another very important approach is that when a new block is defined, zend create a separate symbol table, called active symbol table, for that block and store local variables in that symbol table.

When the code outside the method is executed global symbol is considered active.

To access the symbol table write

EG(symbol_table).

Similarly active symbol table can be accessed as

EG(active_symbol_table);

Data retrieval

How to retrieve value from symbol table and active symbol table?

The code look a bit complex, however I will explain it for you.

Lets we define as

$foo = “bar”;

we can retrieve its value as

zval **result;

if(zend_hash_find(EG(symbol_table), “foo”, sizeof(“foo”), (void**)&result) == FAILURE)

{

php_printf(“value not found”);

return;

} else {

*return_value = **result;

}

We gave zend_hash_find the following parameters.

symbol_table, it can be anything like array in which we want to find the value.

foo, is what we want to find.

sizeof(), is necessary to find how much space the variable we are finding hold.

And last but not the least is the name of the variable where the value, if found is stored.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: