是否有可能直接在Metal API中使用C++

Bil*_*san 9 c++ ios swift metal

由于Metal Language也是基于C++ 11,而C++似乎是一种完美的契合,这是一种经过验证的性能语言,我期待完全绕过Objective-C/Swift.我很想留在C++舞台上.有可能吗?

Tom*_*mmy 7

技术上是的,但它非常难看,可能会破坏其他一些Objective-C部件.

与C++一样,Objective-C作为预处理器开始了.其中一个遗产是每个Objective-C方法也作为C函数调用公开,它将对象实例和方法选择器分别作为前两个参数,然后以从左到右的顺序将其他声明的参数.

双方NSObject以及C调用,形成的Objective-C运行时可以看一下目前的 C函数将被调用任何方法调用.

因此,您可以创建一个C++类来抓取所有C函数指针(它甚至可以从C运行时执行此操作,使其成为纯C++代码而不是Objective-C++)并直接跳转到相应的代码.

缺点是:Objective-C通常使用动态调度(即在每次调用时解析为C函数的方法)和键值观察等机制仅仅因为它使用动态调度.如果你在其他人开始观察之前抓住C函数指针,那么你的调用将在没有通知观察者的情况下更新属性.所以你可能会打破一些模块.

发出警告,并假设您可以将您的C++桥类构建为Objective-C++,以实现更简单的语法,例如

class MTLArray {
    id m_instance;
    static NSUInteger (* s_arrayLength)(id object, SEL selector);
};

MTLArray::MTLArray() {
    // assuming you use the m_ pattern for instance variables
    m_instance = [MTLArray new];

    // assuming you use s_ for static variables; also pretending
    // the mapping from method to C function will never change —
    // KVO is the most prominent exception but otherwise you can
    // be exceedingly confident, albeit you'll be relying on
    // empirical behaviour, not the formal contract
    if(!s_arrayLength) {
        s_arrayLength = [MTLArray instanceMethodForSelector:@selector(arrayLength)];
    }
}

NSUInteger MTLArray::getArrayLength() {
    return s_arrayLength(m_instance, @selector(arrayLength));
}
Run Code Online (Sandbox Code Playgroud)

...我很方便拒绝将结果投到+instanceMethodForSelector:合适的类型,因为我有信心我会弄错.我倾向于typedef在我的实际代码中剔除并引入一个中间件,但你可能更喜欢更简洁.

  • 当然,通过实现这种危险的准静态调度,你可以避免对objc_msgSend的一次调用,但IMP仍然引用一个几乎肯定会调用其他Objective-C方法的函数.因此我的断言是,不可能像OP要求的那样"完全绕过"Objective-C. (3认同)

war*_*enm 1

不会。Metal 仅作为 Objective-C API 公开。最好的情况是,您可以用一组 Objective-C++ 类来包装它,但这只会增加开销,而不是按照您的意愿绕过 Objective-C。