【问题标题】:Pass instance method as function pointer to C Library将实例方法作为函数指针传递给 C 库
【发布时间】:2013-02-15 22:56:19
【问题描述】:

我正在编写一个使用 C 库的 Objective-C 应用程序。我目前面临的问题是 C 库有一个结构,其中一些字段是后来用作回调的函数指针。如何将 Objective-C 实例方法转换为函数指针并将其传递给库?

【问题讨论】:

    标签: objective-c c function-pointers


    【解决方案1】:

    您需要在 Objective-C 类实现文件中提供 C 回调函数,这只有在回调能够使用某种类型的 context 指针时才有效。

    所以想象一下 C 回调签名是这样的:

    void myCallback(void *context, int someOtherInfo);
    

    然后在 Objective-C 类实现文件中,您需要使用该回调跳回到您的 Objective-C 类(使用 context 指针作为要调用的类的实例):

    // Forward declaration of C callback function
    static void theCallbackFunction(void *context, int someOtherInfo);
    
    // Private Methods
    @interface MyClass ()
    - (void)_callbackWithInfo:(int)someOtherInfo;
    @end
    
    @implementation MyClass
    
    - (void)methodToSetupCallback
    {
        // Call function to set the callback function, passing it a "context"
        setCallbackFunction(theCallbackFunction, self);
        ...
    }
    
    - (void)_callbackWithInfo:(int)someOtherInfo
    {
        NSLog(@"Some info: %d", someOtherInfo);
    }
    
    @end
    
    static void theCallbackFunction(void *context, int someOtherInfo)
    {
        MyClass *object = (MyClass *)context;
        [object _callbackWithInfo:someOtherInfo];
    }
    

    如果你的 C 回调函数不接受某种 context 信息,那么:

    1. 已损坏,应将其修复/报告为错误。
    2. 您将需要依赖将 pointer-to-self 存储在供 C 回调函数使用的全局、静态范围内。这会将MyClass 的实例数限制为一个!

    【讨论】:

    • 我想投我的票,“蹦床回来”这个词不知何故成为了这个的官方术语。太棒了。
    • +1 - 如果库不提供void* context 的参数怎么办?
    • @MySpecialPurpose 蹦床这个词恐怕是一个古老的词,而不是我的发明。我是在将 C++ 类与线程创建函数集成时第一次遇到它,需要这样的蹦床方法。
    • 是的,很棒的答案。 :) 谢谢。 我希望我可以再为你的速度投票一次:p
    • @BeccaP 我不确定是否需要转移所有权(我假设)上下文指针“对象”被保留在其他地方。你试过(__bridge MyClass *)吗?
    猜你喜欢
    • 2017-11-26
    • 1970-01-01
    • 2015-02-12
    • 2012-10-22
    • 2011-04-17
    • 1970-01-01
    • 2021-10-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多