有没有办法将 ObjectiveC 块包装成函数指针? [英] Is there a way to wrap an ObjectiveC block into function pointer?

查看:26
本文介绍了有没有办法将 ObjectiveC 块包装成函数指针?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我必须为 iOS 应用程序中的特定 C 库提供 C 风格的回调.回调没有 void *userData 或类似的东西.所以我无法在上下文中循环.我想避免引入全局上下文来解决这个问题.一个理想的解决方案是使用 Objective-C 块.

I have to provide a C-style callback for a specific C library in an iOS app. The callback has no void *userData or something similar. So I am not able to loop in a context. I'd like to avoid introducing a global context to solve this. An ideal solution would be an Objective-C block.

我的问题:有没有办法将块转换"为函数指针或以某种方式包装/隐藏它?

My question: Is there a way to 'cast' a block into a function pointer or to wrap/cloak it somehow?

推荐答案

从技术上讲,您可以访问块的函数指针.但这样做是完全不安全的,所以我当然不推荐它.要了解如何操作,请考虑以下示例:

Technically, you could get access to a function pointer for the block. But it's totally unsafe to do so, so I certainly don't recommend it. To see how, consider the following example:

#import <Foundation/Foundation.h>

struct Block_layout {
    void *isa;
    int flags;
    int reserved; 
    void (*invoke)(void *, ...);
    struct Block_descriptor *descriptor;
};

int main(int argc, char *argv[]) {
    @autoreleasepool {
        // Block that doesn't take or return anything
        void(^block)() = ^{
            NSLog(@"Howdy %i", argc);
        };

        // Cast to a struct with the same memory layout
        struct Block_layout *blockStr = (struct Block_layout *)(__bridge void *)block;

        // Now do same as `block()':
        blockStr->invoke(blockStr);




        // Block that takes an int and returns an int
        int(^returnBlock)(int) = ^int(int a){
            return a;
        };

        // Cast to a struct with the same memory layout
        struct Block_layout *blockStr2 = (struct Block_layout *)(__bridge void *)returnBlock;

        // Now do same as `returnBlock(argc)':
        int ret = ((int(*)(void*, int a, ...))(blockStr2->invoke))(blockStr2, argc);
        NSLog(@"ret = %i", ret);
    }
}

运行结果:

Howdy 1
ret = 1

我们期望通过 block() 直接直接执行这些块.因此,您可以使用 invoke 作为函数指针.

Which is what we'd expect from purely executing those blocks directly with block(). So, you could use invoke as your function pointer.

但正如我所说,这是完全不安全的.不要实际使用它!

如果您想查看有关如何执行您所要求的操作的文章,请查看以下内容:http://www.mikeash.com/pyblog/friday-qa-2010-02-12-trampolining-blocks-with-mutable-code.html

If you want to see a write-up of a way to do what you're asking, then check this out: http://www.mikeash.com/pyblog/friday-qa-2010-02-12-trampolining-blocks-with-mutable-code.html

这只是一篇很好的文章,说明了您需要做什么才能使其发挥作用.遗憾的是,它永远不会在 iOS 上运行(因为您需要将页面标记为可执行文件,而您不允许在应用程序的沙箱中执行此操作).尽管如此,一篇很棒的文章.

It's just a great write-up of what you would need to do to get this to work. Sadly, it's never going to work on iOS though (since you need to mark a page as executable which you're not allowed to do within your app's sandbox). But nevertheless, a great article.

这篇关于有没有办法将 ObjectiveC 块包装成函数指针?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆