Block parsing, block

Source: Internet
Author: User

Block parsing, block
Block Variable

In the previous article, we talked about the features of block and interception variables. Here we will take a look at the _ block variable. Official reference:

You can specify that an imported variable be mutable—that is, read-write— by applying the __block storage type modifier. __blockstorage is similar to, but mutually exclusive of, the registerauto, and static storage types for local variables.

You can read and write data by specifying the _ block storage type modifier. _ Block storage is similar, but mutually exclusive, registers, automatic variables, and local variables and static variable types (not quite understandable in the following sentence ). Let's write an example:
void main1(){    __block char *_para1="a";    printf("init _para1:%s,%p,%p\n",_para1,_para1,&_para1);    void(^testBlock)(void)=^{        printf("exute _para1:%s,%p,%p\n",_para1,_para1,&_para1);    };    _para1="b";    printf("before _para1:%s,%p,%p\n",_para1,_para1,&_para1);    testBlock();    printf("after _para1:%s,%p,%p\n",_para1,_para1,&_para1);}
The output is as follows:
Init _ para1: a, 0x47f4, 0xbfffc9c0
Before _ para1: B, 0x4829, 0x8da4580
Exute _ para1: B, 0x4829, 0x8da4580
After _ para1: B, 0x4829, 0x8da4580

The _ block modifier is added here. The log shows that the address and value of _ para1 inside the block are the same as those of _ para1 before execution. After the block is initialized, the modification of Variable _ para1 can be synchronized to the block, the block does not intercept the variable value. We can look at the cpp Code after clang conversion:

// The object of the block implementation function
struct __block_impl {  void *isa;  int Flags;  int Reserved;  void *FuncPtr;};
// The parameter object referenced by the block (each parameter generates a struct)
struct __Block_byref__para1_0 {  void *__isa;__Block_byref__para1_0 *__forwarding; int __flags; int __size; char *_para1;};
// Block object
struct __main1_block_impl_0 {  struct __block_impl impl;  struct __main1_block_desc_0* Desc;  __Block_byref__para1_0 *_para1; // by ref  __main1_block_impl_0(void *fp, struct __main1_block_desc_0 *desc, __Block_byref__para1_0 *__para1, int flags=0) : _para1(__para1->__forwarding) {    impl.isa = &_NSConcreteStackBlock;    impl.Flags = flags;    impl.FuncPtr = fp;    Desc = desc;  }};
// Block implementation
static void __main1_block_func_0(struct __main1_block_impl_0 *__cself) {  __Block_byref__para1_0 *_para1 = __cself->_para1; // bound by ref        printf("exute _para1:%s,%p,%p\n",(_para1->__forwarding->_para1),(_para1->__forwarding->_para1),&(_para1->__forwarding->_para1));    }
// Other functions (copy and dispose: to manage the memory of the _ Block_byref _ para1_0 struct variable)
static void __main1_block_copy_0(struct __main1_block_impl_0*dst, struct __main1_block_impl_0*src) {_Block_object_assign((void*)&dst->_para1, (void*)src->_para1, 8/*BLOCK_FIELD_IS_BYREF*/);}static void __main1_block_dispose_0(struct __main1_block_impl_0*src) {_Block_object_dispose((void*)src->_para1, 8/*BLOCK_FIELD_IS_BYREF*/);}static struct __main1_block_desc_0 {  size_t reserved;  size_t Block_size;  void (*copy)(struct __main1_block_impl_0*, struct __main1_block_impl_0*);  void (*dispose)(struct __main1_block_impl_0*);} __main1_block_desc_0_DATA = { 0, sizeof(struct __main1_block_impl_0), __main1_block_copy_0, __main1_block_dispose_0};
// This is our test function
void main1(){    __attribute__((__blocks__(byref))) __Block_byref__para1_0 _para1 = {(void*)0,(__Block_byref__para1_0 *)&_para1, 0, sizeof(__Block_byref__para1_0), "a"};    printf("init _para1:%s,%p,%p\n",(_para1.__forwarding->_para1),(_para1.__forwarding->_para1),&(_para1.__forwarding->_para1));    void(*testBlock)(void)=(void (*)())&__main1_block_impl_0((void *)__main1_block_func_0, &__main1_block_desc_0_DATA, (__Block_byref__para1_0 *)&_para1, 570425344);    (_para1.__forwarding->_para1)="b";    printf("before _para1:%s,%p,%p\n",(_para1.__forwarding->_para1),(_para1.__forwarding->_para1),&(_para1.__forwarding->_para1));    ((void (*)(__block_impl *))((__block_impl *)testBlock)->FuncPtr)((__block_impl *)testBlock);    printf("after _para1:%s,%p,%p\n",(_para1.__forwarding->_para1),(_para1.__forwarding->_para1),&(_para1.__forwarding->_para1));}
 

It is found that it is not the same as without _ block. An extra struct (_ Block_byref _ para1_0) is added)

 
struct __Block_byref__para1_0 {  void *__isa;__Block_byref__para1_0 *__forwarding; int __flags; int __size; char *_para1;};
 

This struct is the variable declared with _ block. The code after the _ block Variable _ para1 is converted is as follows:

__attribute__((__blocks__(byref))) __Block_byref__para1_0 _para1 = {(void*)0,(__Block_byref__para1_0 *)&_para1, 0, sizeof(__Block_byref__para1_0), "a"};

In fact, it is to generate a _ Block_byref _ para1_0 object, __forwarding pointer pointing to the variable struct itself

void(*testBlock)(void)=(void (*)())&__main1_block_impl_0((void *)__main1_block_func_0, &__main1_block_desc_0_DATA, (__Block_byref__para1_0 *)&_para1, 570425344);

Initialize the block and pass parameters such as the struct Variable _ para1, function address, and description information. The member _ para1 of the block object references the address of the _ para1 struct. In this way, you can modify the _ para1, in addition, modifications to the _ para1 struct can be synchronized to the member _ para1 of the block object. The modification code is as follows:

(_para1.__forwarding->_para1)="b";

Directly pass_ Block_byref _ para1_0Struct Member_ Forwarding (pointing to itself) obtains the address of the _ para1 member, and then reads and writes the address to modify the variable.

((void (*)(__block_impl *))((__block_impl *)testBlock)->FuncPtr)((__block_impl *)testBlock);

The block is still executed by calling the function pointer.FuncPtrAnd pass the block itself. The function body code is as follows:

static void __main1_block_func_0(struct __main1_block_impl_0 *__cself) {  __Block_byref__para1_0 *_para1 = __cself->_para1; // bound by ref        printf("exute _para1:%s,%p,%p\n",(_para1->__forwarding->_para1),(_para1->__forwarding->_para1),&(_para1->__forwarding->_para1));    }

In the function body (_ Block_byref _ para1_0)And then get _ para1 through its member _ forwarding pointer.

My understanding is the relationship between pointer references. I don't know why I should add a _ forwarding pointer to directly reference my member _ para1. Isn't that true? Hope you can enlighten me.


Who can explain the definition and meaning of the Block type value in the magento template?

The value of type refers to the PHP file corresponding to the block request.

For example, page/html_wrapper is the wrapper method under page/html/wrapper. php or page/html. php.

What does first block mean?

The first block is usually 1st blocks.

Or the first roadblock... you still need to combine the context ..

You can also use the first block in a cinema.
Understandable

Related Article

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.