在C阵列上存储块并在以后运行它们

时间:2014-04-27 12:48:45

标签: objective-c c cocoa block

好的,我可以使用以下内容在NSArrays上存储块:

NSArray *myArray = @[[myBlock1 copy], [myBlock2 copy]];

稍后运行该代码,例如:

myBlockType runBlock = myArray[0];
runBlock(); // run baby, run

与此相当的C怎么样?这可能吗?

2 个答案:

答案 0 :(得分:2)

这有效:

    typedef void (^MyBlockType)(void);

    MyBlockType blocks[100];

    for(int i = 0; i < 100; i++) {
        MyBlockType block= ^{printf("Run!");};
        blocks[i] = block;
    }

    MyBlockType thisBlock = blocks[0];
    thisBlock();

答案 1 :(得分:0)

如果操作系统允许您这样做,您可以将数组的地址分配给函数指针,并使用该指针的名称调用数组中的代码。

typedef void (*fx_t)(void);

int main(void) {
    fx_t udf;
    unsigned char code[1000] = "<<machine code instructions>>";

    udf = code; /* UB: assignment of object pointer to non-object pointer */
                /* illegal assignment according to the Standard */
    udf();
    return 0;
}

根据评论中的请求,这是一个完整的示例,适用于我的计算机(amd64上的FreeBSD 9.2)

#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>

typedef int (*fx_t)(void);

int main(void) {
    int a = -1;
    fx_t udf;
    unsigned char code[1000] = "\xb8\x2a\x00\x00\x00" // mov $0x2a,%eax
                               "\xc3";                // retq
    void *codeaddr = code;

    size_t length = 4096;   /* size of a page */
    if (mprotect(codeaddr, length, PROT_READ | PROT_WRITE | PROT_EXEC)) {
        perror("mprotect");
        exit(EXIT_FAILURE);
    }

    udf = (void*)code;

    a = udf();                   // call the code in the `code` string
    printf("a is now %d.\n", a); // expect 42, changed by the code in `code`

    code[1] = 24;                // w00t! self changing code
    a = udf();
    printf("a is now %d.\n", a); // expect 24

    return 0;
}

为了得到code的字节,我编译了一个非常简单的int fortytwo(void) { return 42; }到目标文件然后objdump -d它并尝试了看似相关的字节(我不知道汇编)语言)

0000000000000000 <fortytwo>:
   0:   55                      push   %rbp
   1:   48 89 e5                mov    %rsp,%rbp
   4:   b8 2a 00 00 00          mov    $0x2a,%eax
   9:   c9                      leaveq
   a:   c3                      retq
   b:   0f 1f 44 00 00          nopl   0x0(%rax,%rax,1)