Суть проблеммы вначале заключалась в том что бы писать форматированный вывод printfа помимо как в OUTPUT еще и в лог файл.
1) Сначала я хотел сделать это через функцию которая вызывает и fprint и printf, но обнаружил что чтобы это сделать необходимо определить число передаваемых параметров и их типы по строке форматирования... в итоге был напсин код на асме который успешно сохраняет кусочек стека в heapе а потом шаманит с указателем стека и вызывает printf и fprint. Все бы нечиго, я даже заделал макрос, который генерит соответсвующие asmные вставки, но по каким то причинам слово Assembler кроме меня никому не греет душу
2) Возникла идея, что раз нельзя что бы функция ето все тварила, то пусть хотя бы макрос, что ему стоит строчке в тексте слепить, но обнаружилось что препроцессор C++ такой ущербный язык, что кажется его таким сделал специально — 'ибо нефиг' . В результате нескольких попыток, был получен слегка корявый вариант, который все таки слепляет агрументы из двух списков для функции с переменным числом агрументов:
// Бубен :)#define __AST *
#define Cc __AST/ //Comment Close#define Co /__AST //Comment Open#define _FUNCCALL(func, h, t) func(Co h Cc, Co t Cc)
// Конец Бубна
// Целывой макрос
FILE* logFile = 0;
#define LOGPRINT(x) \
printf##x; \
if (logFile) _FUNCCALL(fprintf, (Cc logFile Co), x);
// Используется как
LOGPRINT((Cc "Error code: %d. Error Message: %s\r\n", errCode, errMsg Co))
ВОПРОС: Есть у кого идеи как всетаки сделать макрос LOGPRINT чтобы его можно было записать:
LOGPRINT(("Error code: %d. Error Message: %s\r\n", errCode, errMsg)), т.е. без Cc и Co.
а то не красиво смотрится
Кто подскажеть тому
18.08.05 11:38: Перенесено модератором из 'C/C++. Прикладные вопросы' — Павел Кузнецов
// Целывой макрос
FILE* logFile = 0;
#define LOGPRINT(x) \
printf( Co x Cc ); \ // здесь было printf##x
if (logFile) _FUNCCALL(fprintf, (Cc logFile Co), x);
Здравствуйте, rus blood, Вы писали:
RB>Здравствуйте, vnechiporenko, Вы писали:
V>>Кто подскажеть тому
RB>Напиши свою функцию с параметром-строкй и переменным числом аргументов, которая будет вызывать vfprintf. RB>Далее стандартно...
RB>#ifdef _DEBUG RB> #define LOGPRINT myFunc RB>#else RB> #define LOGPRINT 1 ? (void)0 : myFunc RB>#endif
RB>LOGPRINT("Error code: %d. Error Message: %s\r\n", errCode, errMsg);
Текст myFunc попробуй написать и увидишь что не сможешь определить количетсво переданных параметров и их типы (Ну если конечно не писать свой анализатор строки форматирование -- нормальному человеку это делать лень), а как следствие не сможешь их ретранслировать в fprintf. Ну к твоему облегчению я писал уже такую функцию, в ней я использовал вставки на asm'е.. (смотри (1) в моем первом посте). Если вкурсе как написать это без асма то получить много .
Здравствуйте, vnechiporenko, Вы писали:
V> Текст myFunc попробуй написать и увидишь что не сможешь определить количетсво переданных параметров и их типы (Ну если конечно не писать свой анализатор строки форматирование -- нормальному человеку это делать лень), а как следствие не сможешь их ретранслировать в fprintf. Ну к твоему облегчению я писал уже такую функцию, в ней я использовал вставки на asm'е.. (смотри (1) в моем первом посте). Если вкурсе как написать это без асма то получить много .
Ты пишешь под абстрактного коня в вакууме, или под конкретную систему?
Здравствуйте, vnechiporenko, Вы писали:
V> Текст myFunc попробуй написать и увидишь что не сможешь определить количетсво переданных параметров и их типы (Ну если конечно не писать свой анализатор строки форматирование -- нормальному человеку это делать лень), а как следствие не сможешь их ретранслировать в fprintf. Ну к твоему облегчению я писал уже такую функцию, в ней я использовал вставки на asm'е.. (смотри (1) в моем первом посте). Если вкурсе как написать это без асма то получить много .
Впрочем, неважно.
1. Функции типа vfprintf используют va_list для просмотра аргументов.
2. Если подобных функций нет, можно взять готовый код разбора аргументов. Смотри ATLString или MFC CString::Format
Имею скафандр — готов путешествовать!
Re[3]: Препроцессор и переменное число аргументов
От:
Аноним
Дата:
18.08.05 07:51
Оценка:
Здравствуйте, vnechiporenko, Вы писали:
в принципе ссылка уже дана, но на всякий случай
кому лень искать, должно быть примерно так
void Trace( const char *szFormat, ... )
{
va_list arg;
va_start( arg, szFormat ); // Initialize variable arguments
char sMessage[ 1024 ] = { '\0' };
::vsprintf( sMessage, szFormat, arg );
va_end( arg ); // Reset variable arguments
::strcat( sMessage, "\r\n" );
Здравствуйте, rus blood, Вы писали:
RB>1. Функции типа vfprintf используют va_list для просмотра аргументов.
Сори ступил Я только сейчас прочел про vfprintf (не знал о ё суфществовании), действительно рулит... Её спецом похоже для этих целей сделали.
RB>2. Если подобных функций нет, можно взять готовый код разбора аргументов. Смотри ATLString или MFC CString::Format
Угу.. и это дельный совет
Здравствуйте, vnechiporenko, Вы писали:
V>Суть проблеммы вначале заключалась в том что бы писать форматированный вывод printfа помимо как в OUTPUT еще и в лог файл.
V>ВОПРОС: Есть у кого идеи как всетаки сделать макрос LOGPRINT чтобы его можно было записать: V>LOGPRINT(("Error code: %d. Error Message: %s\r\n", errCode, errMsg)), т.е. без Cc и Co. V>а то не красиво смотрится
В библиотеке ACE это уже давно сделано. Вот пример логирования из их Basic_Types_Test.cpp:
Здравствуйте, vnechiporenko, Вы писали:
V>Сори ступил
Ничего страшного Ты не один.
Я тоже не знал о ее существовании, и тоже хотел логирование с форматной строкой сделать, как в printf. А выкрутился установкой исходника MS CRT и компиляцией модифицированной CRT! Был жутко доволен своей изобретательностью, пока не узнал про vprintf
Здравствуйте, pavel_turbin, Вы писали:
_>вроде бы в Linux-e (gcc?) такой наворот есть.
Не только есть, но и прекрасно используется
Макрос с переменным числом параметров — почти как функция.
Удобно — жуть как, незаменим для дебуга
Здравствуйте, arcman, Вы писали:
A>Не только есть, но и прекрасно используется A>Макрос с переменным числом параметров — почти как функция. A>Удобно — жуть как, незаменим для дебуга
Нет, это немного не то. Автор топика хочет, чтобы в дебажной версии были логи, а в релизной нет. Т.е. один дефайн/ундеф — и нету никакого логирования. Или тут тоже как-то можно?
И под C не покатит, так что может оно и лучше, но не так универсально.
Здравствуйте, Сергей, Вы писали:
WM>>IMHO, лучше пользоватся потоками. Определи что-нибудь вроде такого:
WM>>
WM>>log_print << "text: " << 5;
WM>>
С>Нет, это немного не то. Автор топика хочет, чтобы в дебажной версии были логи, а в релизной нет. Т.е. один дефайн/ундеф — и нету никакого логирования. Или тут тоже как-то можно?
Здравствуйте, vnechiporenko, Вы писали:
V>Суть проблеммы вначале заключалась в том что бы писать форматированный вывод printfа помимо как в OUTPUT еще и в лог файл.
[...] V>Кто подскажеть тому
А почему бы не сделать шаблонные заготовки ф-ий, до, скажем, 15-20 аргументов.
Здравствуйте, arcman, Вы писали:
A>Здравствуйте, pavel_turbin, Вы писали:
_>>вроде бы в Linux-e (gcc?) такой наворот есть. A>Не только есть, но и прекрасно используется A>Макрос с переменным числом параметров — почти как функция. A>Удобно — жуть как, незаменим для дебуга
что делает код непортируемый в Windows, т.к. cl не имеет такой поддержки.
Здравствуйте, Centaur, Вы писали:
C>Дальше, оптимизирующий компилятор все обращения к log_print в нелогирующей версии выоптимизирует до нуля.
Не факт.
Боюсь, оптимизатор может не справиться с таким случаем (для этого компилятору пришлось бы доказать, что ни одна из non_inline_functionX не имеет побочных эффектов; может быть, что глобальная оптимизация с этим и справится, но гарантии нет):