Возглавляет: Это - странный вопрос.
У меня есть некоторые действительно полезные макросы, которые мне нравится использовать для упрощения некоторого входа. Например, я могу сделать 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__
заменяется a char*
, и это - вероятно, главный контрольно-пропускной пункт к моему запросу на справку.
Препроцессор выполняет всю свою работу до разбора реального кода. Препроцессор не может знать, является ли функция 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 - они обрабатываются до этапа компиляции.
Таким образом, сам код должен содержать "runtime" проверку (хотя компилятор может оптимизировать ее).
Я бы предложил определять что-то вроде
void *self = nil; //not sure about the types that
SEL _cmd = nil; //would be valid for obj-c
в глобальной области видимости; функции C будут "видеть" эти определения, а методы Objective-C, надеюсь, скроют их своими собственными определениями.
Вы можете использовать что-то вроде условного макроса:
#ifndef OBJECTIVE_C
#define self 0
#define _cmd ""
#endif
Я не совсем уверен, что вы должны определить self
и _cmd
, чтобы эти были только догадки.
Я не уверен, есть ли предопределенный макрос, который вы можете проверить, компилируете ли вы в Objective C, поэтому вам может потребоваться вручную определить OBJECTIVE_C
как часть вашей сборки.