2010-06-13 3 views
7

Heads up: Это странный вопрос.Расширение условного макроса

У меня есть некоторые действительно полезные макросы, которые мне нравятся, чтобы упростить некоторые записи. Например, я могу сделать 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__); 

Это не работает, к сожалению. Я получаю «ошибка:« # »не следует параметр макроса» на моем первом #define.

Моя другая мысль заключалась в создании второго набора макросов, специально для использования в функциях C. Этот запах плохого запаха кода, и я действительно не хочу этого делать.

Есть ли способ использовать один и тот же набор макросов из обоих методов Objective-C и C, и только ссылку self и _cmd, если макрос находится в методе Objective-C?

редактировать больше информации:

thisFunctionIsACFunction определяется в довольно элементарным способом (и я определенно открыт для улучшений и предложений). В основном это так:

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

Он полагается на поведение компилятора предварять «-» или «+» для методов экземпляра и класса на объекты Objective-C. Все остальное должно быть C-функцией (поскольку функции C не могут иметь имена, начинающиеся с «-» или «+»).

Я понимаю, что эта проверка является технически проверкой времени выполнения, поскольку __PRETTY_FUNCTION__ заменяется на char*, и это, вероятно, является основным препятствием для моего запроса о помощи.

+0

Как вы придумали 'thisFunctionIsACFunction'? – 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__); 

не может работать - в #defines обрабатываются до стадии компиляции.

Итак, сам код должен содержать проверку «времени выполнения» (хотя компилятор может оптимизировать это).

Я хотел бы предложить определение что-то вроде

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'd. –

1

Вы можете использовать

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