Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/27.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
目标C类中的混合C函数_C_Objective C_Cocoa_Callback - Fatal编程技术网

目标C类中的混合C函数

目标C类中的混合C函数,c,objective-c,cocoa,callback,C,Objective C,Cocoa,Callback,我正在编写一个Objective-C类,但它使用了一个用C编写的API。这基本上是好的,因为混合使用C调用和Objective-C调用会导致很少的问题 但是,其中一个API调用需要回调方法(示例): 其中MyCFHostClientCallBack是定义如下的C函数: static void MyCFHostClientCallBack(CFHostRef host, CFHostInfoType typeInfo, const CFStreamError *error, void *info)

我正在编写一个Objective-C类,但它使用了一个用C编写的API。这基本上是好的,因为混合使用C调用和Objective-C调用会导致很少的问题

但是,其中一个API调用需要回调方法(示例):

其中
MyCFHostClientCallBack
是定义如下的C函数:

static void MyCFHostClientCallBack(CFHostRef host, CFHostInfoType typeInfo, const CFStreamError *error, void *info);
  • 我可以/如何调用Objective-C方法来代替此方法
  • 我是否可以/应该将C函数与Objective-C调用混合使用
  • 如何将C函数与Objective-C方法混合使用

  • 在这种情况下,我总是发现在C API之上制作一个Obj-C包装器很有帮助。使用C函数实现您需要的功能,并在其上构建一个Objective-C类(或两个),这就是外部世界将看到的所有内容。例如,在这种回调的情况下,您可以创建一个C函数,在其他对象上调用Obj-C委托方法。

    要从C回调调用Objective-C代码,我将使用以下方法:

    void * refToSelf;
    int cCallback()
    {
        [refToSelf someMethod:someArg];
    }
    
    @implementation SomeClass
    - (id) init
    {
         self = [super init];
         refToSelf = self;
    }
    - (void) someMethod:(int) someArg
    {
    }
    

    混合使用C和Objective-C方法和函数是可能的,下面是一个在iPhone应用程序中使用SQLite API的简单示例:()

    下载

    C函数需要在Objective-C(.m)文件中的
    @实现之外声明

    因为C函数在
    @实现之外
    它不能调用

    [self doSomething]
    
    而且无法访问IVAR

    只要回调函数采用
    userInfo
    context
    类型参数(通常为
    void*
    类型),就可以解决这个问题。这可用于将任何Objective-C对象发送到C函数

    与中一样,这可以通过正常的Objective-C操作进行操作

    此外,请阅读以下答案:

    我可以/如何调用Objective-C方法来代替此方法

    你不能

    我可以/应该将C函数与Objective-C调用混合使用吗

    对。编写一个C函数并将其用作CF函数的回调

    如何将C函数与Objective-C方法混合

    您可以将
    self
    设置为上下文结构中的
    info
    指针。这将传递给回调。然后,在回调中,将
    info
    指针投射回
    id

    MyClass *self = (id)info;
    

    然后,您可以发送
    self
    消息。但是,您仍然不能直接访问实例变量,因为C函数不在
    @implementation
    部分。你必须让它们成为你的财产。你可以用一只手来做这件事。(与该文档所说的相反,您不会在
    @implementation
    中声明扩展名,而是在与其相同的文件中声明扩展名,通常位于扩展名的正上方。)

    只需添加一项:许多回调允许指定“用户数据”;在这种情况下,对象指针可以用作用户数据(并且不再需要全局变量refToSelf)。可能是您的回调函数支持info指针中的“用户数据”。使用上述代码,我收到运行时内存泄漏警告,并启用了ARC。这是错误的实现。它假定您只有一个ComeClass实例。void*refToSelf;是一个静态/全局变量。每次[[SomeClass alloc]init]您的refToSelf都将被创建的最后一个实例覆盖。cCallback不会调用正确的SomeClass,而是始终调用最后创建的SomeClass。此外,当最后创建的SomeClass被释放时(至少在上面的代码中),它将崩溃,因为您在SomeClass的dealloc中没有清除refToSelf。要补充@ashcatch所说的:如果您的回调被赋予了
    void*userData
    ,请确保使用
    (_桥id)(用户数据)
    以避免警告和泄漏。如果某个类是单例的,这是可以的。但它不是单例的,请同意@MottiShneor answer。C函数不需要在
    @implementation
    @bavariable:编译器允许您避开
    @implementation
    内部的函数,但它仍然不是
    @implementation的一部分e> ,因为函数不能属于一个类。作为一种风格,我把它放在
    @implementation
    之外,并建议其他人也这样做,以明确这一点。实际上,@implementation块中的C函数具有独特的属性,能够直接访问私有和受保护的IVAR。因此,根据我自己的经验,它是我有一个很强的习惯用法,将“属于”类的C函数放在相应的实现中。我建议更新您的答案。为了澄清,如果允许它们访问类的实例,它们将可以访问私有IVAR。例如,int-MyCFunction(MyClass*self、int-num、void*data)。这与编译-myObjectiveMethod:withData:objc方法时的幕后情况非常相似。@JoshRosen:很有趣,但我认为这只是一个实现细节,而不是明确定义并保证存在的语言功能。
    [self doSomething]
    
    MyClass *self = (id)info;