8

iOS プログラムで C コールバックを必要とするサードパーティ ライブラリを使用しています。コールバックは、void*必要に応じて使用できるユーザーデータ パラメーターを提供します。このコールバックでは、最終的にコールバックを呼び出す API を呼び出すコードに返される NSData オブジェクトを作成したいと考えています。例えば:

// 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 オブジェクトにコピーされるデータを格納するためのバッファだけを保持できると思いますが、その余分な手順を回避できることを望んでいます。

4

2 に答える 2

4

オブジェクトの所有権を に譲渡することはできませんが、オブジェクトの所有権をやvoid*などの CoreFoundation タイプに譲渡することはできます。その後、自由に CF ポインターを渡すことができます。 CFDataRefCFTypeRef

例えば:

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;
    }
}
于 2013-09-16T22:50:23.137 に答える