2010-06-13 13 views
7

Heads up: To dziwne pytanie.Warunkowe rozszerzenie makra

Mam kilka naprawdę użytecznych makr, które lubię w celu uproszczenia niektórych rejestrów. Na przykład mogę zrobić Log(@"My message with arguments: %@, %@, %@", @"arg1", @"arg2", @"arg3"), a to zostanie rozszerzone na bardziej złożone wywołanie metody, które obejmuje takie rzeczy, jak self, _cmd, __FILE__, , itp., Dzięki czemu mogę łatwo śledzić, gdzie rzeczy się logują. Działa to świetnie.

Teraz chciałbym rozszerzyć moje makra, aby nie tylko współpracować z metodami Objective-C, ale także z ogólnymi funkcjami języka C. Problemem są części self i _cmd, które znajdują się w rozszerzeniu makra. Te dwa parametry nie istnieją w funkcjach C. Idealnie chciałbym móc używać tego samego zestawu makr w funkcjach C, ale mam problemy. Kiedy używam (na przykład) mojego makra Log(), dostaję ostrzeżenia kompilatora o self i _cmd będąc niezadeklarowanym (co ma sens).

Moją pierwszą myślą było zrobić coś jak poniżej (w moim makro):

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

To wciąż produkuje ostrzeżenia kompilatora, ponieważ cały if() oświadczenie jest podstawiona w miejsce makra, co skutkuje błędy ze słowami kluczowymi self i _cmd (nawet jeśli nigdy nie zostaną wykonane podczas wykonywania funkcji).

Moja następna myśl, żeby zrobić coś takiego (w moim makro):

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

To nie działa, niestety. Pojawia się "błąd:" # "nie jest poprzedzone przez parametr makro" na moim pierwszym #define.

Moja druga myśl polegała na stworzeniu drugiego zestawu makr, specjalnie do użycia w funkcjach C. To cuchnie złym zapachem kodu, a ja naprawdę nie chcę tego robić.

Czy jest jakiś sposób mogę użyć tego samego zestawu makr zarówno w metodach Objective-C, jak iw funkcjach języka C, a tylko odwołanie self i _cmd, jeśli makro znajduje się w metodzie Objective-C?

edit więcej informacji:

thisFunctionIsACFunction jest określona w dość prymitywny sposób (i jestem zdecydowanie otwarty na ulepszenia i sugestii). W zasadzie to jest tak:

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

To polegając na zachowanie kompilatora poprzedzić znakiem „-” lub „+” dla instancji i metod na obiektach klasy Objective-C. Coś innego musi być funkcją C (ponieważ funkcje C nie mogą mieć nazw zaczynających się od "-" lub "+").

Rozumiem, że ta kontrola jest technicznie sprawdzana w czasie wykonywania, ponieważ __PRETTY_FUNCTION__ zostaje zastąpiona przez char* i jest to prawdopodobnie główna przeszkoda w mojej prośbie o pomoc.

+0

Jak można wymyślić 'thisFunctionIsACFunction'? – Artelius

+0

@Artelius zredagowane pytanie z więcej informacji –

Odpowiedz

7

Procesor wykonuje całą swoją pracę, zanim zostanie przeanalizowany rzeczywisty kod. Preprocesor nie może wiedzieć, czy funkcja jest C lub obj-C, ponieważ działa przed parsowaniem kodu.

Z tego samego powodu,

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

nie może pracować - to #defines są przetwarzane przed etapie kompilacji.

Sam kod musi zawierać kontrolę "w czasie wykonywania" (choć kompilator może to zoptymalizować).

Proponuję definiowania coś

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

w zakresie globalnym; funkcje C będą "widzieć" te definicje, podczas gdy metody Objective-C miejmy nadzieję, że ukryją je za pomocą własnych definicji.

+0

+1 Ha! Jesteś geniuszem! Nigdy bym nie pomyślał o zdefiniowaniu 'self' i' _cmd' na poziomie globalnym! Dzięki! (I działa idealnie, po prostu próbowałem.) –

0

Można użyć jakiegoś makro Warunkowo:

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

nie jestem pewien, co należy określić self i _cmd aby były to tylko domysły.

Nie jestem pewien, czy istnieje predefiniowane makro, które można sprawdzić, czy kompilujesz w Objective C, więc może być konieczne zdefiniowanie ręcznie OBJECTIVE_C jako części kompilacji.

+0

Dobry pomysł. Jedynym problemem jest to, że Objective-C jest ścisłym nadzbiorem C, co oznacza, że ​​ObjC i C mogą spokojnie współistnieć obok siebie. Oznacza to, że większość moich funkcji C będzie miała '__OBJC__' # define'd. –

1

Można użyć

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