Условное расширение макроса

Heads up: это странный вопрос.

у меня есть очень полезные макросы, которые мне нравится использовать для упрощения некоторых журналов. Например я могу сделать Log(@"My message with arguments: %@, %@, %@", @"arg1", @"arg2", @"arg3"), и это будет расширено в более сложный вызов метода, который включает в себя такие вещи, как self, _cmd, __FILE__, __LINE__ и т. д., чтобы я мог легко отслеживать, где все регистрируется. Это отлично работает.

теперь я хотел бы расширить свои макросы, чтобы не только работать с методами Objective-C, но и общие функции C. Проблема в self и _cmd части, которые находятся в расширении макроса. Эти два параметра не существуют в функциях C. В идеале я хотел бы иметь возможность использовать этот же набор макросов в функциях C, но у меня возникают проблемы. Когда я использую (например) my Log() макрос, я получаю предупреждения компилятора о self и _cmd быть необъявленным (что имеет полный смысл).

моей первой мыслью было сделать что-то вроде следующего (в моем макрос):

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

это все еще создает предупреждения компилятора, так как весь оператор if () заменяется вместо макроса, что приводит к ошибкам с 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, и только reference self и _cmd если макрос находится в методе Objective-C?

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

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

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

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

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

3 ответов


препроцессор выполняет всю свою работу до фактического анализа кода. Препроцессор не может знайте, является ли функция 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, надеюсь, скроют их своими собственными определениями.


можно использовать

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

вы можете использовать какой-то макрос условное:

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

Я не совсем уверен, что вы должны определить self и _cmd чтобы это были просто догадки.

Я не уверен, есть ли предопределенный макрос, который вы можете проверить, компилируете ли вы в Objective C, поэтому вам может потребоваться определить OBJECTIVE_C вручную как часть сборки.