2009-04-29 3 views
37

Objective-C 클래스를 작성하고 있지만 C로 작성된 API를 사용합니다. Objective-C 호출로 C 호출을 혼합하면 거의 문제가 없으므로 대부분 잘됩니다.Objective-C 클래스의 C 함수 섞기

static void MyCFHostClientCallBack(CFHostRef host, CFHostInfoType typeInfo, const CFStreamError *error, void *info); 
  1. 수/어떻게 수행 MyCFHostClientCallBack는 다음과 같이 정의 된 C 함수이다

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

    그러나

    API 호출 중 하나

    은 콜백 방법 (예)가 필요합니다 이 대신에 Objective-C 방법을 호출 하시겠습니까?
  2. Objective-C 호출과 함께 C 함수를 혼합 할 수 있습니까?
  3. C 함수를 Objective-C 메서드와 어떻게 섞을 수 있습니까?

답변

48

과 기능이 가능, 여기 내 SQLite는 API를 사용하는 간단한 예입니다 아이폰 앱 (course site)

Zip file (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 

[self doSomething] 

같은 메소드를 호출 인스턴스 변수에 액세스 할 수없는 수없는 C 함수는 @implementation의 외부이기 때문이다.

이 한 콜백 기능이 정상적으로 유형 void*으로하는 userInfo 또는 context 유형의 매개 변수를 같이 해결할 수 있습니다. 이것은 Objective-C 객체를 C 함수로 보내는 데 사용할 수 있습니다.

sample code에서와 같이 정상적인 Objective-C 작업으로 조작 할 수 있습니다. Mixing C functions in an Objective-C class

+26

C 함수는'@ implementation'의 외부에있을 필요는 없습니다. –

+12

@Bavarious : 컴파일러는'@ implementation' 내부의 함수를 없앨 수는 있지만 함수는 클래스에 속할 수 없으므로 여전히'@ implementation'의 일부가 아닙니다. 스타일의 문제로, 나는 그것을 @ 구현의 외부에두고, 다른 사람들에게도 똑같이하도록 권하고있다. –

+20

실제로 @implementation 블록의 C 함수는 개인 및 보호 된 ivars에 직접 액세스 할 수있는 고유 한 특성을 가지고 있습니다. 따라서 내 자신의 경험으로 볼 때, 해당 구현 내부의 클래스에 속한 C 함수를 배치하는 것은 강력한 관용구가되었습니다. 답변을 업데이트하는 것이 좋습니다. –

5

이 상황에서 항상 도움이되는 부분은 C API 위에 Obj-C 래퍼를 만드는 것입니다. C 함수를 사용하기 위해 필요한 것을 구현하고 그 위에 Objective-C 클래스 (또는 두 개)를 빌드하면 모든 외부 세계에서 볼 수 있습니다. 예를 들어, 이와 같은 콜백의 경우 다른 객체에서 Obj-C 대리자 메서드를 호출하는 C 함수를 만들 수 있습니다.

25

내가 좋아하는 뭔가를 사용하는 것 C 콜백에서 오브젝티브 C 코드를 호출하려면 : C와 목표 - C 방법을 혼합

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

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

많은 콜백이 "사용자 데이터"를 지정할 수 있습니다. 이 경우 오브젝트 포인터를 사용자 데이터로 사용할 수 있습니다 (더 이상 전역 변수 refToSelf를 사용할 필요가 없습니다). 콜백 함수가 정보 포인터에서 "사용자 데이터"를 지원할 수도 있습니다. – ashcatch

+0

위의 코드를 사용하여 ARC를 활성화 한 상태에서 런타임 메모리 누수 경고가 표시됩니다. http://stackoverflow.com/questions/11840943/runtime-memory-leaked-warnings-when-executing-objective-c-code-within-c-code-wit – docchang

+2

이것은 버그 구현입니다. 그것은 ComeClass 인스턴스가 하나만 있다고 가정합니다. void * refToSelf; 정적/전역 변수입니다. [[SomeClass alloc] init] 때마다 refToSelf는 마지막으로 생성 된 인스턴스에 의해 덮어 쓰여질 것입니다. cCallback은 올바른 SomeClass를 호출하지 않고 항상 마지막으로 생성 된 것입니다. 게다가 SomeClass의 dealloc에 ​​대해 refToSelf를 지우지 않기 때문에 마지막으로 생성 된 SomeClass가 해제 될 때 (적어도 위의 코드에서) 충돌합니다. –

8

/어떻게이 대신에 목표 - C 방식 호출 할 수 있습니다 : 또한

이 대답을 읽어보십시오?

수 없습니다.

Can/Objective-C 호출에서 C 함수를 사용해야합니까?

예. C 함수를 작성하고이를 CF 함수의 콜백으로 사용하십시오.

어떻게 C 함수를 Objective-C 메서드와 함께 사용합니까?

info 포인터는 컨텍스트 구조에 self으로 설정할 수 있습니다. 그것은 콜백에 전달됩니다. 그런 다음, 콜백, id에 다시 info 포인터를 캐스팅 : 그런 다음 self 메시지를 보낼 수 있습니다

MyClass *self = (id)info; 

. C 함수가 @implementation 섹션 외부에 있기 때문에 여전히 인스턴스 변수에 직접 액세스 할 수 없습니다. 속성을 만들어야합니다. class extension으로이 작업을 수행 할 수 있습니다. (이 문서가 말하는 것과는 반대로, 확장자는 @implementation 안에 선언하지 말고, 그 파일의 바로 위에있는 파일과 같습니다.)