gpt4 book ai didi

ios - C 回调如何通过用户数据指针返回 Objective-C 对象?

转载 作者:可可西里 更新时间:2023-11-01 03:13:25 26 4
gpt4 key购买 nike

我在 iOS 程序中使用需要 C 回调的第三方库。回调提供了一个 void* 用户数据参数,我可以根据需要使用它。在此回调中,我想创建一个 NSData 对象,该对象返回到调用最终调用回调的 API 的代码。例如:

// C callback:
static void callback(int x, void* userdata)
{
if (userdata)
{
// This gives an error:
// Pointer to non-const type 'NSData*' with no explicit ownership
NSData** p = (NSData**)userdata;

*p = [NSData init:...];
}
}

// main code:
NSData* d = ...; // sometimes valid, sometimes nil
library_api(callback, &d); // have the callback initialize or replace d
if (d)
{
[d doSomthing:...];
}

我正在使用 ARC,我认为这是问题的根源。我想过使用结构来保存 NSData*,但 ARC 禁止在结构或联合中使用 Objective-C 对象。可能有一些 __bridge 的变体可能有帮助,但我不确定是哪个。我已经查看了很多 SO 问题并阅读了 Apple 文档,但我不清楚如何对其进行编码。

理想情况下,如果在调用回调时 d 不为 nil,则将释放其当前值并用一个新的 NSData 对象替换它。换句话说,当 library_api 完成时,d 始终持有由回调创建的 NSData 对象,并且任何先前持有的值都会被适本地释放。

我想我可以将 Objective-C 代码保留在回调之外,而只是 malloc() 一个缓冲区来存储数据,然后将其复制到主代码中的 NSData 对象,但是我希望我可以避免这个额外的步骤。

最佳答案

您不能将对象所有权转移到 void*,但您可以将对象所有权转移到 CoreFoundation 类型,例如 CFDataRefCFTypeRef。然后您可以随意传递 CF 指针。

例如:

NSData* data = ...

CFTypeRef cfData = (__bridge CFTypeRef)data; // If you want to pass in data as well.

library_api(callback, &cfData);

if (cfData)
{
data = (__bridge_transfer NSData*)cfData; // Transfer ownership to ARC. No need to call CFRelease(cfData).
NSLog@("Data: %@", data);
}

在回调中:

static void callback(int x, void* userdata)
{
if (userdata)
{
CFTypeRef* cfDataPtr = userdata;

CFTypeRef cfInData = *cfDataPtr;
NSData* inData = (__bridge NSData*)cfInData;
NSLog(@"In Data: %@", inData);

NSData* outData = [[NSData alloc] init];
CFTypeRef cfOutData = (__bridge_retained CFTypeRef)outData; // Transfer ownership out of ARC.
*cfDataPtr = cfOutData;
}
}

关于ios - C 回调如何通过用户数据指针返回 Objective-C 对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18837933/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com