2010-06-13 5 views
7

헤드 업 : 이상한 질문입니다.조건부 매크로 확장

일부 로깅을 간소화하기 위해 내가 사용하기를 좋아하는 매크로가 있습니다. 예를 들어 Log(@"My message with arguments: %@, %@, %@", @"arg1", @"arg2", @"arg3")을 수행하면 self, _cmd, __FILE__, __LINE__ 등을 포함하는보다 복잡한 메소드 호출로 확장되어 로깅되는 위치를 쉽게 추적 할 수 있습니다. 이것은 잘 작동합니다.

이제 매크로를 확장하여 Objective-C 메서드뿐만 아니라 일반적인 C 함수도 사용할 수 있도록 확장하고 싶습니다. 문제는 매크로 확장에있는 self_cmd 부분입니다. 이 두 매개 변수는 C 함수에 없습니다. 이상적으로 C 함수 내에서 동일한 매크로 집합을 사용할 수 있기를 원하지만 문제가 발생합니다. (예를 들어) 내 Log() 매크로를 사용하면 self_cmd에 대한 컴파일러 경고가 표시됩니다 (총칭 함).

내 첫번째 생각은 다음 (내 매크로)처럼 뭔가를했다 :

if (thisFunctionIsACFunction) { 
    DoLogging(nil, nil, format, ##__VA_ARGS__); 
} else { 
    DoLogging(self, _cmd, format, ##__VA_ARGS__); 
} 

을이 전체 경우() 문의 결과로, 매크로 대신에 치환되기 때문에 여전히 컴파일러 경고를 생성합니다 self_cmd 키워드로 오류가 발생합니다 (함수 실행 도중에 실행되지는 않지만).

나의 다음 생각은 (내 매크로)이 그런 짓을했다 :

if (thisFunctionIsACFunction) { 
    #define SELF nil 
    #define CMD nil 
} else { 
    #define SELF self 
    #define CMD _cmd 
} 
DoLogging(SELF, CMD, format, ##__VA_ARGS__); 

불행히도 작동하지 않습니다. 나는 "error : '#'매크로 팩터가 뒤 따르지 않는다."라고 내 첫 번째로 말하면 #define입니다.

제 생각에 다른 두 번째 매크로 집합은 특히 C 함수에서 사용하기위한 것입니다. 나쁜 냄새가 나는 냄새가 나는데 정말로은 이것을 원하지 않습니다.

Objective-C 메서드와 C 함수 내에서 동일한 매크로 집합을 사용할 수 있습니까? 매크로가 Objective-C 메서드 인 경우 self_cmd 만 참조 할 수 있습니까?

편집 자세한 내용은 :

thisFunctionIsACFunction은 아주 초보적인 방법으로 결정된다 (그리고 나는 개선 및 제안을 확실히 열려있어). 기본적으로이 : 씁니다 컴파일러의 동작에 의존하는 것

BOOL thisFunctionIsACFunction == (__PRETTY_FUNCTION__[0] != '-' && __PRETTY_FUNCTION__[0] != '+'); 

에 '-'또는 '+'목표 - C 개체의 인스턴스와 클래스 메소드. C 함수는 '-'또는 '+'로 시작하는 이름을 가질 수 없으므로 다른 함수는 C 함수 여야합니다.

__PRETTY_FUNCTION__char*으로 바뀌므로이 검사는 기술적으로 런타임 검사임을 이해합니다. 이는 아마도 도움 요청에 대한 주요 장애물 일 것입니다.

+0

를 사용할 수 있습니까? – Artelius

+0

@Artelius는 (는) 더 많은 정보를 가지고 질문을 편집했습니다. –

답변

7

전처리 기는 실제 코드가 파싱되기 전에 모든 작업을 수행합니다. 전 처리기 은 코드가 구문 분석되기 전에 실행되기 때문에 함수가 C 또는 obj-C인지 여부를 알 수 없습니다 (). 같은 이유로

,
if (thisFunctionIsACFunction) { 
    #define SELF nil 
    #define CMD nil 
} else { 
    #define SELF self 
    #define CMD _cmd 
} 
DoLogging(SELF, CMD, format, ##__VA_ARGS__); 

이 작동하지 않을 수 있습니다 - # 정의는 컴파일 단계 전에 처리됩니다.

따라서 코드 자체에는 "런타임"검사가 포함되어야합니다 (컴파일러가이를 최적화 할 수도 있음).

내가

전역에서
void *self = nil; //not sure about the types that 
SEL _cmd = nil; //would be valid for obj-c 

같은 것을 정의하는 제안; C 함수는 이러한 정의를 "볼"있지만 Objective-C 메서드는 자체 정의로 해당 메서드를 숨길 수 있습니다.

+0

+1 하! 너는 천재 야! 저는 글로벌 수준에서'self'와'_cmd'를 정의 할 생각이 전혀 없었을 것입니다! 감사! (그리고 그것은 완벽하게 작동합니다, 방금 시도했습니다.) –

0

당신은 매크로 조건의 일종 사용할 수 있습니다

#ifndef OBJECTIVE_C 
    #define self 0 
    #define _cmd "" 
#endif 

나는 당신이 self_cmd을 정의해야하는지 아주 잘 모르겠습니다을, 사람들은 단지 추측했다.

Objective C에서 컴파일 중인지 확인할 수있는 사전 정의 된 매크로가 있는지 확인해야하므로 OBJECTIVE_C을 빌드의 일부로 수동으로 정의해야 할 수도 있습니다.

+0

좋습니다. 유일한 문제는 Objective-C가 C의 엄격한 상위 집합이므로 ObjC와 C가 함께 평화롭게 공존 할 수 있다는 것입니다. 이것은 내 C 함수 대부분이'__OBJC__' #define을 가질 것임을 의미합니다. –

1

당신은 당신이`thisFunctionIsACFunction`와 방법을 마련 할

if defined "abc" <statement1> 
else if defined "def" <statement2>