Resource data types for PHP

Source: Internet
Author: User
Tags arrays resource zend

Resource data type

So far, you've been working on very basic user space data types, strings, values, True/false equivalents. Even if you've started touching arrays in the previous chapter, you're just collecting arrays of these underlying data types.

Complex structural body

In the real world, you usually need to work in a more complex set of data, often involving obscure structural pointers. A common example of an obscure structural body pointer is the stdio file descriptor, even if it is only a pointer in the C language.

#include <stdio.h>  
int main (void)  
{  
    FILE *fd;  
    FD = fopen ("/home/jdoe/.plan", "R");  
    Fclose (FD);  
    return 0;  
}

The Stdio file descriptor is consistent with most other file descriptors, like a bookmark. Your extended invocation application only needs to pass this value in Feof (), Fread (), fwrite (), fclose (), and so on when implementing function calls. Sometimes, this bookmark must be accessible by user-space code; Therefore, it is necessary to have a method in the standard PHP variable or Zval * that represents it.

A new type of data is needed here. The resource data type stores a simple integer value in Zval *, which is used as an index to locate the registered resource. Resource entries contain information such as the internal data type represented by the resource index, and pointers to store resource data.

Defining resource types

To make the resource information contained in the registered resource entry more explicit, you need to define the type of resource. First, add the following code snippet to the existing function implementation in your SAMPLE.C

static int le_sample_descriptor;  
Php_minit_function (sample)  
{  
    le_sample_descriptor = ZEND_REGISTER_LIST_DESTRUCTORS_EX (  
                null, NULL, PHP _sample_descriptor_res_name,  
                module_number);  
    return SUCCESS;  
}

Next, scroll to the end of your code file, modify the sample_module_entry structure, and replace the null,/* Minit */Line with the following. Just as you add the function list structure to this structure, you need to make sure that you keep a comma at the end of the line.

Php_minit (sample),/* minit * *

Finally, you need to define Php_sample_descriptor_res_name in Php_sample.h, and place the following code under your other constants definition:

#define PHP_SAMPLE_DESCRIPTOR_RES_NAME "File descriptor"

Php_minit_function () represents the first of the 4 special startup and termination operations described in chapter 1th, "PHP Lifecycle," which will be discussed in depth in chapter 12th, "Start, end, and key points between" and chapter 13th "INI Settings".

A very important thing to know here is that the Minit function executes once when your extension is first loaded, and it is executed before all requests arrive. Here we take this opportunity to register the destructor, but they are null values, but you will soon modify it if it is sufficient to know a resource type through a unique integer ID.

Registering resources

Now that the engine knows that you want to store some resource data, it's time to give user-space code a way to generate actual resources. To do this, you need to implement the following fopen () command:

Php_function (Sample_fopen)  
{  
    FILE *fp;  
    Char *filename, *mode;  
    int Filename_len, Mode_len;  
    if (Zend_parse_parameters (Zend_num_args () TSRMLS_CC, "SS",  
                        &filename, &filename_len,  
                        &mode, &mode_len) = = failure) {  
        return_null ();  
    }  
    if (!filename_len | |!mode_len) {  
        php_error_docref (NULL tsrmls_cc, e_warning,  
                "Invalid filename or mode length ");  
        Return_false;  
    }  
    fp = fopen (filename, mode);  
    if (!FP) {  
        php_error_docref (NULL tsrmls_cc, e_warning,  
                "Unable to open%s using mode%s",  
                filename, mode);  
        return_false;  
    }  
    Zend_register_resource (Return_value, FP,  
                                le_sample_descriptor);  
}

In order for the compiler to know what file * is, you need to include stdio.h. This can be put in sample.c, but for the later part of this chapter, I'm going to ask you to put it in the php_sample.h.

If you work the previous chapters, all the content in front of the last line should be readable. This line of code performs the task of storing the FP pointer in the index of the resource, associating it with the type defined in Minit, and storing a key into return_value that can be used to find it.

If you need to store more than one pointer value, or if you store a direct amount, you must allocate a new section of memory to store the data, and then register the pointer to that memory as a resource.

Nasa

1. The registration of a resource data type actually inserts a newly constructed zend_rsrc_list_dtors_entry structure into the list_destructors (static global variable Hashtable defined in zend/zend_list.c). This structure describes the information for this resource type.

2. The registration of resource data (Zend_register_resource) actually uses zend_hash_next_free_element () in eg (regular_list) to get the next numeric subscript as the ID of the resource, The incoming resource pointer (encapsulated as a zend_rsrc_list_entry structure) is stored in the element corresponding to the subscript in eg (regular_list).

3. EG (regular_list) is initialized in the request initialization phase, and by tracking code you can see the function call flow as follows: Php_request_startup (MAIN/MAIN.C)--> zend_active (Zend /ZEND.C)--> Init_compiler (zend/zend_compile.c)--> zend_init_rsrc_list (zend/zend_list.c). By observing the zend_init_rsrc_list () function, we can see that the destructor of eg (Regular_list) is List_entry_destructor (zend/zend_list.c). The logic of the List_entry_destructor () is to find information about the type of resource object to release from List_destructors (the static global variable described in the first step above), and then to refactor the destructor specified by registering the resource type.

4. According to the above points, it is easy to clarify what is described earlier in this chapter. First registers a resource type that contains information such as the owning module number, the destructor handle. Then, when you create a specific resource object, you associate the resource object with the resource type.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.