Как использовать макрос C (#define) для изменения вызовов, но не прототипов
Старый код в нашем приложении содержит призывы к malloc
, realloc
а также free
, С нашим обновленным кодом наши собственные реализации вызываются вместо стандартных реализаций. Примеры приведены ниже,
#define malloc(s) OurMalloc(s)
#define free(p) OurFree(p)
Это прекрасно работает для обновленного кода и для более нового кода C++, мы просто реализуем глобальный new
а также delete
операторы, поэтому решение C++ "чище".
Проблема в том, что теперь мы должны включить стороннюю библиотеку, в которой есть классы, содержащие методы с такими именами, как malloc
а также free
например,
class ABC
{
public:
...
void free (char *p);
};
Если свободный метод класса имеет одинаковое количество аргументов, препроцессор C/C++ просто заменяет все вхождения free
от ourFree
даже в определении класса, даже при вызове метода, свободного от класса ABC
, Итак, определение класса выше и следующий вызов:
ABC abc;
abc.free(p);
заменены на,
class ABC
{
public:
...
void OurFree (char *p);
};
ABC abc;
abc.OurFree(p);
Который может компилироваться, но который не связывает конечно.
Если ABC::free
количество аргументов отличается от стандартного free, компилятор по-прежнему выдает предупреждение. мы хотели бы избежать их.
Некоторые альтернативные решения:
- отмена определения в начале стороннего включаемого файла и переопределение его позже
- убедитесь, что сторонний включаемый файл всегда включен до нашего собственного определения
Но даже в этом случае, если нашему коду требуется вызывать эти malloc или свободные методы сторонних классов, препроцессор все равно будет изменять вызовы, если мы не напишем все вызовы следующим образом:
(abc::free)(p)
Есть ли способ сказать, что препроцессор C/C++ определяет это?
- должны быть заменены только чистые C-звонки
- прототипы НЕ ДОЛЖНЫ быть заменены
- методы в классах НЕ ДОЛЖНЫ заменяться
3 ответа
Препроцессор ничего не знает о масштабах и семантике. Такой короткий ответ - нет, вы не можете этого сделать.
Но вы можете использовать #undef free
в библиотечных модулях. С другой стороны - это не поможет, если вы вызываете методы abc.free()
из вашего кода.
Как насчет определения только этих замен для C, а не C++:
#ifndef __cplusplus
# define malloc(s) OurMalloc(s)
# define free(p) OurFree(p)
#endif
Почему бы вам просто не определить свои собственные функции malloc и free вместо использования макросов.
Итак, измените:
void *OutMalloc (size_t s)
чтобы:
void *malloc (size_t s)
так же, как вы можете перезаписать оператор new и удалить.
Я думаю, хотя я могу ошибаться, компоновщик будет искать в объектных файлах символы, прежде чем искать в библиотеках.