вторник, 24 марта 2009 г.

Асинхронный ввод/вывод с libevent

Один из проектов, которым я сейчас занимаюсь, для работы с сокетами использует механизм kqueue. Мне необходимо модифицировать бизнес-логику, часть которой захватывает отправку отправку ответа, но поскольку некоторые данные приходится модифицировать непосредственно перед отправкой, код обработки события EVFILT_WRITE сильно размазался.
Я решил перенести сетевой асинхронный ввод/вывод на библиотеку libevent. На официальном сайте есть неплохая документация в Doxygen и скудненький пример, который оказался не совсем рабочим: событие EV_READ срабатывает постоянно.
Собрал на FreeBSD 6.2, 6.3, 7.0 – баг повторяется. Чтоб событие отрабатывалось корректно и вовремя, очередь надо открывать с правами O_RDWR, а не с O_RDONLY.

вторник, 10 марта 2009 г.

CodeCamp 2009...

...или еще одна возможность встретиться и пообщаться вживую.
28-29 марта 2009 года в городе Киев пройдет всеукраинская конференция, посвященная разработке программного обеспечения. Программа конференции многопоточна, так что заранее желательно определиться, куда идти.
Помимо программирования, будут доклады по управлению и работе в команде.

Зарегистрироваться можно
здесь
Думаю, будет интересно.

суббота, 7 марта 2009 г.

Прозрачное журналирование с wxLog

В wxWidgets есть отличный механизм журналирования wxLog.
С его помощью можно решить проблему ведения лога одновременно в файл и, например, в текстовый контрол.

Если необходимо выводить сообщения в файл не только в ANSI, а и в Unicode,
то очень удобно использовать логгер wxLogStream.
Для его использования, потребуется собрать (если еще не собрано) wxWidgets с выставленной поддержкой std потоков. Для этого необходимо выставить соответствующую
директиву в файле setup.h:

#define wxUSE_STD_IOSTREAM 1


После этого, в приложении потребуется установить целевой логгер:

//wxTestApp.h
// в классе приложения добавить мембер потока
...
#include
...

class wxTestApp: public wxApp
{
...
private:
std::ofstream m_logStream;
...
};

//wxTestApp.cpp
// в OnInit() проинициализировать целевой логгер

bool wxCDCreatorApp::OnInit() {
// задаем имя лога (в каталоге приложения, файл <имя файла приложения>.log
wxString logPath = wxPathOnly(wxGetApp().argv[0])
+ wxFileName::GetPathSeparator()
+ GetAppName()
+ wxT(".log");
m_logStream.open(logPath.GetData());

// не забываем удалить предыдущий логгер
delete wxLog::SetActiveTarget(new wxLogStream(reinterpret_cast<std::ostream*>(&m_logStream)));

// можно работать
wxLogMessage(wxT("Запуск приложения..."));
...
// инициализация приложения
}

// и в OnExit() закрываем поток
int wxCDCreatorApp::OnExit()
{
wxLogMessage(wxT("Выход..."));
m_logStream.close();
return wxApp::OnExit();
}


После этого, в любой части приложения возмножно с помощью функций wxLogMessage, wxLogDebug (только в отладочной версии),
wxLogTrace вести журналирование. В результате работы, в лог пишутся сообщения в примерно таком формате:


09:55:05: Запуск приложения...

четверг, 5 марта 2009 г.

Сборка библиотеки avcap для Windows

Итак, поэкспериментировав с различными библиотеками захвата видео, я остановился
на кроссплатформенной библиотеке avcap. Сайт проекта находится здесь.
Отличная документация к библиотеке идет в пакете с проектом. Также, есть
простенький, но понятный пример использования.

Почему я выбрал именно avcap:
1. Кроссплатформенность.
Реализация под Windows использует DirectShow, под Linux - V4L, под Mac OS X - QuickTime.
2. Написана на C++.
3. Работает достаточно стабильно.
4. Легко интегрируется с С++ проектом.

Из минусов стоит отметить проблемную сборку под Windows.
Под Linux и Mac OS X сборка и установка не вызвала никаких проблем, стандартная процедура:
./configure
make
sudo make install

Для успешной сборки avcap под Windows (XP, Vista) необходимо подготовить следующее:
1. Установить Microsoft Visual Studio (2008).
2. Установить Microsoft DirectX SDK (2008 November).
3. Установить Microsoft Windows SDK 7.
4. Скопировать каталог
C:\Program Files\Microsoft SDKs\Windows\v7.0\Samples\Multimedia\DirectShow\BaseClasses\

например в C:\Temp.
5. Снять атрибут "Только чтение с BaseClasses".
6. Открыть baseclasses.sln, согласиться на конвертацию в новый формат.
7. Выбрать цель Debug.
8. В зависимости от проекта, возможно прийдется изменить Runtime Library на Multi-threaded Debug.
9. Собрать.
10. В настройках путей Visual Studio убедиться, что пути к DirectX SDK находяться ниже,
чем пути Windows SDK.


11. С предыдущего Platform SDK взять qedit.h и закоментировать в нем упоминания
dxtrans.h и IDXEffect. Этот файл можно положить в каталог baseclasses.


Настройка проекта avcap.
1. Открыть avcap.sln, согласиться сконвертировать.
2. В свойствах проекта указать:
Character Set: Use Unicode Character Set
Additional Include Directories: C:\Temp\BaseClasses;C:\Program Files\Microsoft SDKs\Windows\v7.0\Include";..\include\avcap\windows;..\include\avcap;
Runtime Library: Multi-threaded Debug (/MTd)
4. Открываем файл avcap\avcap\windows\ds_devicedescriptor.cpp
находим строчку (477) и правим ее:
wsprintf((LPWSTR)ws, L"FilterGraph %08x pid %08x\0", (DWORD_PTR)pUnkGraph, GetCurrentProcessId());

5.Собираем библиотеку.

В настройки приложения, которое будет использовать avcap, нужно добавить следующее:
в C/C++:
Preprocessor Definitions: AVCAP_WINDOWS
и в Linker:
Additional Dependencies: avcapd.lib strmbasd.lib uuid.lib ole32.lib winmm.lib strmiids.lib oleaut32.lib


Сборка была протестирована на Windows XP SP2 и на Windows Vista SP1.
Основной источник проблем заключался в порядке путей к заголовочным файлам,
так что будьте внимательнее.

вторник, 3 марта 2009 г.

Сборка Windows SDK 7

После установки, первое, что удивило - это замена makefile в Samples на sln+vcproj.
Хоть что-то изменилось.

Скопировал весь каталог BaseClasses в рабочий каталог и открыл в студии проект.
Студия предложила сконвертировать в новый формат. Сконвертировал, собираю...

>amfilter.cpp
1>c:\program files\microsoft sdks\windows\v7.0\include\objidl.h(11265) :
error C2061: syntax error : identifier '__RPC__out_xcount_part'
1>c:\program files\microsoft sdks\windows\v7.0\include\objidl.h(11266) :
error C2059: syntax error : ')'
1>c:\program files\microsoft sdks\windows\v7.0\include\objidl.h(11266) :
fatal error C1903: unable to recover from previous error(s); stopping compilation

Проблема оказалась в путях к заголовочным файлам, вернее в их порядке.
Переместив C:\Program Files (x86)\Microsoft DirectX SDK\Include в самый конец все
собралось на отлично.

Сборка avcap.

В 7 SDK удалили файл qedit.h!
Взял этот файл из SDK 6.0A.
Вернулась проблема dxtrans.h, которого все-таки больше не существует.

Отредактировал qedit.h

//#include "dxtrans.h" -- Line 498
IDxtCompositor //: public IDXEffect -- Line 837
IDxtAlphaSetter //: public IDXEffect -- Line 1151
IDxtJpeg //: public IDXEffect -- Line 1345
IDxtKey //: public IDXEffect -- Line 1735

Пересобираю... опять гора ошибок.
Оказывается, в SDK есть такие же заголовочные файлы, как и в
Samples\Multimedia\DirectShow\BaseClasses. Ладно, переставил порядок,
поставил Samples перед SDK.
Пересобираю...

1>c:\temp\avcap\avcap\windows\ds_devicedescriptor.cpp(477) :
error C2664: 'wsprintfW' : cannot convert parameter 1 from 'char [128]' to 'LPWSTR'
1> Types pointed to are unrelated; conversion requires reinterpret_cast,
C-style cast or function-style cast

"Жопой чую, конец близко" (с) Макс

Быстро поправляю типы данных и преобразования, пересобираю и вуаля!

1>avcap - 0 error(s), 0 warning(s)
2>captest - 0 error(s), 0 warning(s)
========== Build: 2 succeeded, 0 failed, 0 up-to-date, 0 skipped ==========

Протестировал, все работает на отлично.

Все просто!

воскресенье, 1 марта 2009 г.

Windows Development Hell

Текущий проект заставил меня вернуться к программированию под Windows.
Прошло два дня активной работы и у меня уже сдают нервы.
Я конечно все понимаю, но не так же все плохо?

Собираю библиотеку libavcap. Она требует Platform SDK, ок, ставлю.
Дальше, BaseClasses захотели DirectX SDK. Ну, скачал поставил.
А оно не работает! Оказывается разработчики или ответственные за
сборку пакета "забыли" добавить файлик dxtrans.h, начал гуглить, действительно.
Причем, эта проблема, как я понял, уже с давних пор. Ждут исправления в Windows 7. Шок.

Порадовал дизайн инсталлятора DirectX.
Почему именно Check Box там, где должен быть Radio Button? Умом их не понять...


Собирая strmbasd.lib, намучался с путями Development Environment Command Prompts.
То они видят cl и не видят link, то не видят вообще ничего...

Во время сборки nmake останавливался раза четыре. Из-за ошибок в коде.

Например, в файле outputq.cpp:635 был код, примерно следующего вида:
for (long iDone = 0;....;) {
}
*nSamplesProcessed = iDone - iLost;


Старый стандарт, это понятно. Но SDK-то не старый!!!
И так еще в 3 файлах и более чем в 10 местах. Поправив все вручную, вроде собралось.

Кстати, при сборке и запуске Register Development Environment Variables у меня пропал файл,
или студия начала ссылаться на несуществующий... mspdb80.dll

Нашел, скопировал, студия перестала вообще что-либо собирать.
Вручную отредактировал пути поиска програм и библиотек,
удалил библиотеку - вроде заработало.

Итого, двое суток мозгосношений и ни строчки собственного кода в попытке сборки чужого.

Становится все интереснее...