Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/26.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
Ios C回调如何通过userdata指针返回Objective-C对象?_Ios_Objective C_Callback_Automatic Ref Counting - Fatal编程技术网

Ios C回调如何通过userdata指针返回Objective-C对象?

Ios C回调如何通过userdata指针返回Objective-C对象?,ios,objective-c,callback,automatic-ref-counting,Ios,Objective C,Callback,Automatic Ref Counting,我正在使用一个第三方库,它需要在iOS程序中使用C回调。回调提供了一个void*userdata参数,我可以随意使用它。在这个回调中,我想创建一个NSData对象,该对象返回到调用最终调用回调的API的代码中。例如: // C callback: static void callback(int x, void* userdata) { if (userdata) { // This gives an error: // Pointer to no

我正在使用一个第三方库,它需要在iOS程序中使用C回调。回调提供了一个
void*
userdata参数,我可以随意使用它。在这个回调中,我想创建一个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对象。可能有一些
\u bridge
的变体可能会有所帮助,但我不确定是哪个。我已经看了很多这样的问题,并阅读了苹果的文档,但我不清楚如何编写代码

理想情况下,如果在调用回调时d不是nil,则会释放其当前值,并用一个新的NSData对象替换它。换句话说,当library_api完成时,d始终保存回调创建的NSData对象,以前保存的任何值都会被正确释放


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

可以让struct包含ObjC对象,它们必须是
\uu未恢复的\u不安全的
或在.mm文件中

有几个选择:

1使用结构将ObjC对象保存在.m文件中

struct MyStruct
{
    __unretained_unsafe id obj;
}
< P > 2使用结构在file(ObjuleC++)中保存Objc对象,并使用C++<代码>新建/删除< /代码>。您可以这样做,因为编译器将在结构的构造函数/析构函数中生成retain/release

struct MyStruct
{
    id obj; // no need to have __unretained_unsafe
}
3更改回调函数的签名并强制转换它(我以前没有尝试过)


4只需使用
-fno objc ARC
编译器标志将此文件设为非ARC即可您不能将对象所有权转移到
void*
,但可以将对象所有权转移到CoreFoundation类型,如
CFDataRef
CFTypeRef
。然后,您可以根据需要自由地传递CF指针

e、 g:

在回调中:

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;
    }
}
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;
    }
}