Как правильно перехватить аргумент элипсис?
От: пффф  
Дата: 07.06.23 20:11
Оценка:
Привет!

В общем, не помню, ка коно правильно называется, ... как в printf.

Есть допустим функция int some_cool_printf(const char* format, ...).
Сорцов нет, версии с va_args нет, я хочу сделать прокладку типа:

int with_log_some_cool_printf(const char* format, ...)
{
    // do something with args
    return some_cool_printf(...);
}

#define some_cool_printf with_log_some_cool_printf

// ...


Просто так это не сделать, насколько помню. Тут, по идее, выручил бы не вызов, а переход по адресу some_cool_printf. Ну, и with_log_some_cool_printf должна быть declspec(naked) или как-то так.

Интересует Win32/64, и MSVC, но и про более общие решения было бы интересно узнать.

Вроде бы declspec(naked) нет в x64, не?

А что если тупо goto вкорячить, прокатит?
    goto some_cool_printf;


Или через какие-то setjump'ы извращаться?
Или вручную нагенерить инструкции перехода? Как это правильно сделать? Может, есть что-то подобное готовое?
Re: Как правильно перехватить аргумент элипсис?
От: koenjihyakkei Россия  
Дата: 07.06.23 20:23
Оценка: +1
Здравствуйте, пффф, Вы писали:

Можно попробовать сделать with_log_some_cool_printf через parameters pack:

template<typename... Args>
int with_log_some_cool_printf(const char *format, Args... args) {
  // do something with parameter pack arguments
  return some_cool_printf(format, args...);
}
Re[2]: Как правильно перехватить аргумент элипсис?
От: пффф  
Дата: 07.06.23 20:26
Оценка:
Здравствуйте, koenjihyakkei, Вы писали:

K>Можно попробовать сделать with_log_some_cool_printf через parameters pack:


K>
K>template<typename... Args>
K>int with_log_some_cool_printf(const char *format, Args... args) {
K>  // do something with parameter pack arguments
K>  return some_cool_printf(format, args...);
K>}
K>


Для современных плюсов прокатит, но что делать со старым кодом, который не всегда даже плюсовый, а нужно в основном туда
Re: Как правильно перехватить аргумент элипсис?
От: watchmaker  
Дата: 07.06.23 21:42
Оценка:
Здравствуйте, пффф, Вы писали:

П>Просто так это не сделать, насколько помню.

Да, на чистом С или С++ это не реализуется.
Поэтому нормальной практикой считается предоставлять функции с va_args, если предоставляются функции с ellipsis.

П> Может, есть что-то подобное готовое?

Библиотеки libffi, dyncall и другие реализации FFI как раз позволяют вызывать функции из других языков. В том числе и когда нужно позвать из C/C++ какую-то другую функцию на С/C++ с ellipsis.
Re[3]: Как правильно перехватить аргумент элипсис?
От: Zhendos  
Дата: 07.06.23 21:47
Оценка: +2
Здравствуйте, пффф, Вы писали:

П>Для современных плюсов прокатит, но что делать со старым кодом, который не всегда даже плюсовый, а нужно в основном туда


В C99 есть возможность использовать макросы с произвольным
количеством аргументов:

#define my_printf(...) do { \
  //do_sometingn
  printf(__VA_ARGS__); \
} while (0)
Re[2]: Как правильно перехватить аргумент элипсис?
От: пффф  
Дата: 07.06.23 22:57
Оценка:
Здравствуйте, watchmaker, Вы писали:

П>>Просто так это не сделать, насколько помню.

W>Да, на чистом С или С++ это не реализуется.

Наверно, надо в в более другом форуме спрашивать


W>Поэтому нормальной практикой считается предоставлять функции с va_args, если предоставляются функции с ellipsis.


Хотя присмотрелся — вроде бы есть такие версии

W>Библиотеки libffi, dyncall и другие реализации FFI как раз позволяют вызывать функции из других языков. В том числе и когда нужно позвать из C/C++ какую-то другую функцию на С/C++ с ellipsis.


Спасибо
Re[4]: Как правильно перехватить аргумент элипсис?
От: пффф  
Дата: 07.06.23 22:58
Оценка:
Здравствуйте, Zhendos, Вы писали:

Z>В C99 есть возможность использовать макросы с произвольным

Z>количеством аргументов:

Z>
Z>#define my_printf(...) do { \
Z>  //do_sometingn
Z>  printf(__VA_ARGS__); \
Z>} while (0)
Z>


Ну, наверно я не всё описал. Еще хочется это всё запилить в библиотеку, которую подсовывать уже собранному коду
Re[5]: Как правильно перехватить аргумент элипсис?
От: Zhendos  
Дата: 08.06.23 07:27
Оценка:
Здравствуйте, пффф, Вы писали:

П>Ну, наверно я не всё описал. Еще хочется это всё запилить в библиотеку, которую подсовывать уже собранному коду


Ну если имеется ввиду что-нибудь типа LD_PRELOAD, то можно
использовать "gcc" для сборки dll/so которую будут "встраивать" в чужой код:


int printf_hook(char *fmt, ...)
{
    void *arg = __builtin_apply_args();
    void *ret = __builtin_apply((void*)printf, arg, MAX_NUMBER_OF_ARGUMENTS);
    __builtin_return(ret);
}
Re[6]: Как правильно перехватить аргумент элипсис?
От: пффф  
Дата: 08.06.23 09:32
Оценка:
Здравствуйте, Zhendos, Вы писали:

П>>Ну, наверно я не всё описал. Еще хочется это всё запилить в библиотеку, которую подсовывать уже собранному коду


Z>Ну если имеется ввиду что-нибудь типа LD_PRELOAD, то можно

Z>использовать "gcc" для сборки dll/so которую будут "встраивать" в чужой код:


Z>
Z>int printf_hook(char *fmt, ...)
Z>{
Z>    void *arg = __builtin_apply_args();
Z>    void *ret = __builtin_apply((void*)printf, arg, MAX_NUMBER_OF_ARGUMENTS);
Z>    __builtin_return(ret);
Z>}
Z>


Пока больше MSVC интересует, но в принципе для общего развития это тоже интересно
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.