Макрос C для изменения только вызовов функций, а не определений функций - PullRequest
0 голосов
/ 29 мая 2018

У меня очень похожие вопросы: Макрос и функция с тем же именем

Я хочу, чтобы макрос изменял только вызовы функций, а не сам функционал

#define original_function(a, b) replace_function(a, b)

uint64_t replace_function(int a, int b) {
    // some functionallity
}

uint64_t original_function(int a, int b) {
    // some functionallity
}

uint64_t main(uint64_t argc, uint64_t* argv) {
    original_function(10, 20);
}

это может привести к изменению исходного определения функции

#define original_function(a, b) replace_function(a, b)

uint64_t replace_function(int a, int b) {
    // some functionallity
}

uint64_t replace_function(int a, int b) {
    // some functionallity
}

uint64_t main(uint64_t argc, uint64_t* argv) {
    original_function(10, 20);
}

Я не могу этого сделать (что является ответом в связанном вопросе)

uint64_t (original_function)(int a, int b) {
    // some functionallity
}

//...

И я не могу поставить определение послефункция

uint64_t original_function(int a, int b) {
    // some functionallity
}

#define original_function(a, b) replace_function(a, b)

// ...

Можно ли как-то определить в макросе изменение только вызовов функций, а не определений функций?Или я могу как-то определить макрос, чтобы переименовать только исходную функцию (не вызов), чтобы на нее не влияли?

Редактировать: Я могу изменить только макрос, а не код послечто ...

1 Ответ

0 голосов
/ 31 мая 2018

Вы можете "сопоставить шаблон" со строкой, в которой находится определение, используя препроцессор Си.Чтобы сделать это полезным способом, сначала вам нужен косвенный макрос SECOND:

#define SECOND(...) SECOND_I(__VA_ARGS__,,)
#define SECOND_I(A,B,...) B

... затем полезно иметь косвенный GLUE:

#define GLUE(A,B) GLUE_I(A,B)
#define GLUE_I(A,B) A##B

... и, наконец, "выборочно синяя краска" original_function на себя, если и только если она появляется на определенной строке (этот подход требует выяснения, на какой линии он находится, но я бы посоветовал не разборчиво с этим странным запросом):

#define original_function(a,b) \
   SECOND(GLUE(EXCEPT_FOR_LINE_,__LINE__),replace_function)(a,b)

Таким образом, этот макрос расширит original_function двумя аргументами с replace_function, учитывая, что первый созданный токен не определен.Но если этот первый токен определен, то токен раскрывается первым, после чего выбирается второй аргумент для , что .Это означает, что вы можете сделать это:

#define EXCEPT_FOR_LINE_6 ,original_function

... и если original_function фактически определена в строке 6 (и не вызывается в строке 6), то окончательное расширение выглядит как оригинальное ...по строке 6;и во всех других строках он сгенерирует вызов replace_function.

В этом примере использует эту технику в вашем коде.И в качестве бонуса, все макросы, описанные выше в этом примере, определяются в командной строке (в соответствии с вашим предполагаемым использованием в комментариях).

...