web-dev-qa-db-ja.com

Objective-CクラスでのC関数の混合

Objective-Cクラスを作成していますが、Cで作成されたAPIを使用しています。C呼び出しとObjective-C呼び出しを混在させると問題はほとんど発生しないため、これで問題はほとんどありません。

ただし、API呼び出しの1つには、コールバックメソッドが必要です(例):

success = CFHostSetClient(Host, MyCFHostClientCallBack, &context);

MyCFHostClientCallBackは、次のように定義されたC関数です。

static void MyCFHostClientCallBack(CFHostRef Host, CFHostInfoType typeInfo, const CFStreamError *error, void *info);
  1. これの代わりにObjective-Cメソッドを呼び出すことができますか、どのように呼び出すことができますか?
  2. C関数とObjective-C呼び出しを混在させることはできますか、すべきですか?
  3. C関数とObjective-Cメソッドを混在させるにはどうすればよいですか?
38
rjstelling

CとObjective-Cのメソッドと機能を混在させることが可能です。iPhoneアプリ内でSQLite APIを使用する簡単な例を次に示します。( course site

Zipファイル(09_MySQLiteTableView.Zip) をダウンロードします

C関数は、Objective-C(.m)ファイルの@implementationの外側で宣言する必要があります。

int MyCFunction(int num, void *data)
{
     //code here...
}

@implementation

- (void)MyObjectiveCMethod:(int)number withData:(NSData *)data
{
      //code here
}

@end

C関数は@implementationの外部にあるため、次のようなメソッドを呼び出すことはできません

[self doSomething]

ivarsにはアクセスできません。

これは、コールバック関数がuserInfoまたはcontext型パラメーター(通常はvoid*型)をとる限り回避できます。これを使用して、Objective-CオブジェクトをC関数に送信できます。

サンプルコード のように、これは通常のObjective-C操作で操作できます。

さらに、この回答をお読みください: Objective-CクラスでのC関数の混合

48
rjstelling

CコールバックからObjective-Cコードを呼び出すには、次のようなものを使用します。

void * refToSelf;
int cCallback()
{
    [refToSelf someMethod:someArg];
}

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

これの代わりにObjective-Cメソッドを呼び出すことができますか、どのように呼び出すことができますか?

できません。

Objective-C呼び出しにC関数を混在させることはできますか/すべきですか?

はい。 C関数を記述し、CF関数へのコールバックとして使用します。

C関数とObjective-Cメソッドを混在させるにはどうすればよいですか?

selfをコンテキスト構造のinfoポインターとして設定できます。それはコールバックに渡されます。次に、コールバックで、infoポインターをidにキャストします。

MyClass *self = (id)info;

その後、selfメッセージを送信できます。ただし、C関数は@implementationセクションの外側にあるため、インスタンス変数に直接アクセスすることはできません。それらをプロパティにする必要があります。 クラス拡張 でこれを行うことができます。 (その文書が述べていることとは反対に、@implementation内で拡張子を宣言するのではなく、それと同じファイルで、一般的にはそのすぐ上で宣言します。)

8
Peter Hosey

この状況で私がいつも助けになっているのは、C APIの上にObj-Cラッパーを作成することです。 C関数を使用するために必要なものを実装し、その上にObjective-Cクラス(または2つ)を構築します。これにより、外の世界がすべて見えるようになります。たとえば、このようなコールバックの場合、他のオブジェクトのObj-Cデリゲートメソッドを呼び出すC関数を作成できます。

5