суббота, 30 апреля 2011 г.

Компилируем wxWidgets приложение для Windows из под FreeBSD

Можно скомпилировать приложение minimal из примеров, поставляемых вместе с wxWidgets.
Использовать будем mingw-cross-env, да к стати из портов можно установить mercurial, чтоб установить последнюю версию mingw-cross-env для этого запускаем:

hg clone http://hg.savannah.nongnu.org/hgweb/mingw-cross-env

Чтоб добыть обновления, запускаем:

hg pull -u


В общем после установки wxwidgets, т.е. после выполнения команд:

cd mingw-cross-env
gmake wxwidgets


В директории с кодом простого wxWidgets приложения выполним:

i686-pc-mingw32-g++ minimal.cpp -o minimal.exe `i686-pc-mingw32-wx-config --cxxflags --libs`

В текущей директории появляется minimal.exe, правда его размер несколько впечатляет почти 7 Мбайт. Можно его уменьшить командой:

i686-pc-mingw32-strip minimal.exe

Почти в два раза.

wine minimal.exe

При записке minimal.exe под Windows 98 , а также wine, при условии, что там в настройках (команда winecfg) стоит Windows 98, может вылести сообщение "wxWidgets Fatal Error\n This program uses Unicode and requires Windows NT/2000/XP ...". Ничего страшного, можно просто перекомпилировать minimal.cpp без поддержки Unicode.

i686-pc-mingw32-g++ minimal.cpp -o minimal.exe `i686-pc-mingw32-wx-config -nounicode --cxxflags --libs`


Об опциях i686-pc-mingw32-wx-config можно узнать командой:

i686-pc-mingw32-wx-config

правда не все опции могут в действительности дать желаемый эффект, например, думал, что опция --release уменьшит размер файла за счет исключения отладочной информации, ну да ладно, strip есть.

суббота, 23 апреля 2011 г.

Компиляция для Windows из под FreeBSD

Ставил mingw32 из портов, результат не очень.
Но вот набрел на страницу http://mingw-cross-env.nongnu.org
Сделал:
В FreeBSD должно быть установлено: automake111 autoconf268 bash bison cmake flex gmake gsed intltool libtool openssl patch perl p5-XML-Parser pkg-config scons unzip wget yasm
И ещё wine для проверки работоспособности кода.

0. cd ~/mingw32
1. wget https://bitbucket.org/vog/mingw-cross-env/downloads/mingw-cross-env-2.20.tar.gz
2. tar -xzvf mingw-cross-env-2.20.tar.gz
3. cd mingw-cross-env-2.20
4. gmake download-gcc
Возможны проблемы с загрузкой этой командой, но можно и скачать обычным способом. То, что не сможет через скрипт скачать, можно подсмотреть в папке pkg, потестив архивы, можно ещё подсмотреть откуда качает в директории src , найдя соответствующий .mk файл
5. gmake gcc
можно приписать и другие порты после gcc, например, gmake gcc gdb и т.д.
6. редактирую ~/.cshrc , добавляю строку :
setenv PATH ~/mingw/mingw-cross-env-2.20/bin:$PATH
так как использую SHELL=csh,
для SHELL=bash в файле ~/.profile можно прописать:
export PATH = ~/mingw/mingw-cross-env-2.20/bin:$PATH
7. Компилить прогу написанную на Си можно так
i686-pc-mingw32-gcc -o main.exe main.c
8. А, запускать так
wine main.exe

вторник, 15 марта 2011 г.

Отображение кириллических символов в консоли

1. Вариант
Использовать широкие символы
Редактор кода настраивается на ввод символов в кодировке UTF-8
Settings -> Editor… -> General Settings -> Other settings -> Encoding и выбрать UTF-8.
Теперь в тексте программы один символ кодируется двумя байтами, тип которого соответствует wchar_t (тип данных стандарта ANSI/ISO C для представления широких символов). Теперь в программе надо использовать функции, которые умеют обрабатывать wchar_t символы и корректно выполнять ввод/вывод. Обычно имена функций работающих с wchat_t начинаются с символа ‘w’, стоящим перед именем аналогичной функции, но работающей с char, например,
int wprintf( const wchar_t *format [, argument]... ) ; /*аналогична printf */
int wscanf( const wchar_t *format [, argument]... ) ; /* scanf */

В Windows API, тип wchar_t имеет размер 16 бит.
В GNU/Linux тип wchar_t имеет размер 32 бита.

Пример:
/*Компилятор MinGW*/
#include <stdio.h>
#include <stdlib.h>
#include <locale.h>

int main()
{
setlocale(0,".866");/*Локаль, без этой строки не будет работать*/
wprintf(L"Привет!\n"); /*L – указываем, что используются широкие символы в строке*/
return 0;
}

2. Вариант
Использовать Win32Api функцию CharToOem
Текст программы имеет кодировку WINDOWS-1251 или ANSI, функция CharToOem вызывается обычно перед выводом в консоль какого-либо текста с кириллическими символами.

Пример:
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>

int main()
{
char s[] = "Текст";
CharToOem(s,s);/*Перекодируем s, после этого вызова s меняет своё значение*/
printf("%s",s);
return 0;
}

3. Вариант
Использование шрифта Lucida Console в консоли
// установить вручную шрифт Lucida Console в свойствах окна консоли
// и запомнить это для всех окон с этим именем
// записать в начале программы строку
#include <windows.h>
// записать в начале функции main ()
// две следующих строки
SetConsoleCP(1251);
SetConsoleOutputCP(1251);

4. Вариант
Использовать опций компилятора для перекодировки текста программы из UTF-8 в CP866. Понятно, что можно использовать и другое направление перекодировки, типа WINDOWS-1251 в CP866. В консоли должна быть доступна команда iconv.
В командной строке делаем, например, так
gcc -finput-charset=UTF-8 -fexec-charset=CP866 main.c -o main

В CodeBlocks можно прописать эти опции в параметры компиляции для проекта
Project -> Build options -> Compiler settings -> Other options
Записываем строку:
-finput-charset=UTF-8 -fexec-charset=CP866

5. Вариант
Если используется компилятор от Microsoft (cl.exe), то достаточно прописать только локаль, строка в функции main():
setlocale(0,””);

пятница, 19 ноября 2010 г.

Вопрос претенденту на вакансию "Программист C++"

На нескольких сайтах, предлагающих вакансию программиста C++, встречаются одни и те же вопросы, например, на сайте вакансий yandex. Один из них такой:
Перечислите все проблемы, которые вы видите в данном коде:


1 class Foo
2 {
3 public:
4 Foo(int j) { i=new int[j]; }
5 ~Foo() { delete i; }
6 private:
7 int* i;
8 };
9
10 class Bar: Foo
11 {
12 public:
13 Bar(int j) { i=new char[j]; }
14 ~Bar() { delete i; }
15 private:
16 char* i;
17 };
18
19
20 void main()
21 {
22 Foo* f=new Foo(100);
23 Foo* b=new Bar(200);
24 *f=*b;
25 delete f;
26 delete b;
27 }



В результате медитации, получил следующий, несовершенный код, но все же отражающий моё понимание проблем:

1 class Bar;//Добавил, чтоб в классе Foo использовать имя класса Bar
2
3 class Foo
4 {
5 public:
6 Foo(int j)
7 {
8 i=new int[j];
9 }
10 Foo() {} //Добавил, т.к. нужен конструктор по умолчанию, если бы Foo(int),
» небыло, то он бы был сгенерирован компилятором

11 ~Foo()
12 {
13 delete[] i; //Изменил, добавив [], а то удалять будет не весь массив, а
» только первый элемент массива с индексом 0, т.е. получим утечку памяти

14 }
15
16 Foo operator=(const Bar& r_)//Добавил оператор присваивания, и по идее надо
» делать глубокое копирование по членам, но для этого обеспечить доступ к полю
» Bar::i, вариантов может быть несколько

17 {
18 //На самом деле дальше код должен быть более сложный
19 delete[] i; //в общем, то надо ещё поработать с динамической памятью,
» убрать, то, что там было создано конструктором Foo(int), а то будет утечка
» памяти

20 return Foo();//сделаем так для простоты
21 }
22
23
24
25 private://Возможно надо заменить private на protected, чтоб дочерний класс мог
» обращаться к полю Foo::i

26 int* i;
27 };
28
29 class Bar: public Foo //добавил public
30 {
31 public:
32 Bar(int j)
33 {
34 i=new char[j];
35 }
36 ~Bar()
37 {
38 delete[] i; //Изменил, добавив []
39 }
40
41 private:
42 char* i;
43 };
44
45
46 int main()
47 {
48 Foo* f=new Foo(100);
49 Foo* b= new Bar(200); //Нужно в классе определить присваивание и чтоб было
» открытое наследование

50 *f=*b; //Нужно в классе определить присваивание
51 delete f;
52 delete b;
53 }



Ах, да, похоже, что надо ещё создать конструктор копирования Foo(const Foo&), надо повозится с глубоким копированием, сделать проверки в операторе присваивания, чета стало лень копать дальше.

пятница, 8 октября 2010 г.

Исчезли папки и файлы на съемном диске (flash)

Иногда подходят ко мне с проблемой, мол исчезли файлы и папки на диске. Делаю так:
Пуск - Выполнить..., набираю cmd, предположим, что съемный диск имеет имя H:\, забиваем в консоли следующее:

cd /D H:\
attrib -S -H -R *


Подробности об attrib, делаем так:

attrib /?


Интересно, что чем более удобной и технологически продвинутой становится Windows, тем больше возможностей для появления в системе вирусов. Например, файл autorun.ini в корне диска, созданный для автоматического открытия диска (запуска программ), позволяет распространять "заразу" от одного компьютера другому, путем простого подключения съемного диска.

четверг, 7 октября 2010 г.

Мета-тег от Яндекса

Добавил мета-тег от Яндекса, надеюсь, что в скором времени будет больше посещений блога, в тем более, что по некоторым оценкам, Яндекс используют как поисковую систему примерно 45% пользователей Рунета.
Добавил вот этот код проверки:

1 <meta name='yandex-verification' content='40d5e3ee817d41b6' />


Идентификатор содержит 16 символов, каждый шифрует 4 бита, 16*4=64 бита или 8 байт.
Не расточительство ли это?
Обещали проверять его наличие.

воскресенье, 26 сентября 2010 г.

Простои проект C++ с использованием wxWidgets

Понадобится кроссплатформенная утилита bakefile для поддержки генерации make-файлов и файлов-проектов для разных платформ и сред программирования. Для её использования понадобится python. Будем считать, что с установкой wxWidgets справились все. У меня, например, для этого создан командный файл build_cl.cmd в каталоге %WXWIN%\build\msw. %WXWIN% - переменная среды, содержащая путь к wxWidgets (не должен содержать пробелов). Использую, компилятор C++ идущий вместе с Microsoft Visual C++ 2005 Express Edition, установил его без IDE и MSDN, ещё установлен MS PSDK для работы.

call vcvars32
nmake -f makefile.vc MONOLITHIC=0 SHARED=0 UNICODE=1 BUILD=release
pause

В директории проекта создадим поддиректорию build, в ней создадим файл app.bkl, следующего содержания:


1 <?xml version="1.0" ?>
2 <!-- $Id$ -->
3
4 <makefile>
5
6 <!-- Путь к файлу wx.bkl, хотя можно их таскать в
۠отдельной директории с именем presets в
۠директории проекта -->

7 <include file="C:/wxWidgets-2.9.1/build/bakefiles/wxpresets/presets/wx.bkl" />
8
9 <!-- Определяем переменную BUILDDIR в стиле wxWidgets -->
10 <set-wxlike-builddir> </set-wxlike-builddir>
11
12 <exe id="app" template="wxgui">
13
14 <debug-info>off</debug-info>
15 <runtime-libs>dynamic</runtime-libs>
16
17 <!-- Здесь всякие опции для линковщика -->
18 <ldflags cond="FORMAT=='msvc'">/OPT:REF</ldflags>
19 <ldflags cond="FORMAT=='msvc'">/OPT:ICF</ldflags>
20 <ldflags cond="FORMAT=='msvc6prj'">/entry:"wWinMainCRTStartup"</ldflags>
21
22 <!-- Исходники -->
23 <sources>$(fileList('../src/*.cpp'))</sources>
24 <headers>$(fileList('../src/*.h'))</headers>
25 <win32-res>$(fileList('../src/*.rc'))</win32-res>
26 <symbian-res>$(fileList('../src/*.rss'))</symbian-res>
27
28 <!-- Здесь используемые в проекте библиотеки
۠wxWidgets -->

29 <wx-lib>core</wx-lib>
30 <wx-lib>base</wx-lib>
31 </exe>
32
33 </makefile>



Как видим, используется XML-формат. Чтобы bakefile не ругался на строки, где содержатся кириллические символы, файл должен быть в кодировке UTF-8. Имена тегов должны быть в нижнем регистре.

Для генерации makefile.vc использую командный файл, следующего содержания:

bakefile -f msvc app.bkl
call vcvars32
pause

Для сборки проекта использую командный файл, следующего содержания:

nmake /f makefile.vc WX_MONOLITHIC=0 WX_SHARED=0 WX_UNICODE=1 WX_DEBUG=0
pause


Исходники, файлы ресурсов и заголовочные файлы находятся в папке src.
В простейшем случае, там расположены следующие файлы:
app.h
app.cpp
frame.h
frame.cpp
minimal.rc
mondrian.ico
mondrian.xpm

Содержание файла app.h :

1 #include <wx/app.h>
2 #if !defined(__WXMSW__) && !defined(__WXPM__)
3 #include "mondrian.xpm"
4 #endif
5
6 #include "frame.h"
7
8 class App : public wxApp
9 {
10 public:
11 virtual bool OnInit();
12 };


Содержание файла app.cpp :

1 /// app.cpp
2 #include "app.h"
3
4 bool App::OnInit()
5 {
6 if ( !wxApp::OnInit() )
7 return false;
8
9 Frame *frame = new Frame(_T("Только фрейм"));
10 frame->Show(true);
11 return true;
12 }
13
14 IMPLEMENT_APP(App)



Содержание файла frame.h :

1 #include <wx/frame.h>
2 class Frame : public wxFrame
3 {
4 public:
5 Frame(const wxString& title);
6 private:
7 DECLARE_EVENT_TABLE()
8 };
9
10 //Идентификаторы элементов управления, которые должны реагировать на события
11 enum
12 {
13
14 };
15
16



Содержание файла frame.cpp :

1 #include "frame.h"
2
3 //Таблица событий для связи методов и идентификаторов с определенным типом
» сообщения

4 BEGIN_EVENT_TABLE(Frame, wxFrame)
5
6 END_EVENT_TABLE()
7
8 // Конструктор
9 Frame::Frame(const wxString& title)
10 : wxFrame(NULL, wxID_ANY, title)
11 {
12 SetIcon(wxICON(mondrian_xpm));
13 }
14



Содержание файла ресурсов minimal.rc :

mondrian_xpm ICON "mondrian.ico"
#include "wx/msw/wx.rc"