Home

Записки разработчика

Грабли, Трюки, Хитрости

О тонкостях работы с UTF-8 в Symbian OS C++

[18 November 2009, 18:16]

При обработке входящих данных внутри приложения, возникает необходимость перевести их из 8 битного представления, в 16 битное.

По теории, делается это в принципе просто, где str1 -> HBufC16* , aBytes HBufC8*

str1=HBufC::NewL(aBytes.Length());
str1->Des().Copy(aBytes);

Но. При таком копировании русские буквы превратятся в крякозябры.

Правильно - использовать include utf.h (Не забудьте добавить LIBRARY charconv.lib) в mmp файл
Формат представления данных внутри Symbian OS - Unicode,

Тогда мы имеем такую конструкцию:

str1=HBufC::NewL(aBytes.Length()*2);
str1=CnvUtfConverter::ConvertToUnicodeFromUtf8L(aBytes);

Внимание: Выделять памяти надо ровно в 2 раза больше, иначе возникнет ошибка USER 42. В связи с тем, что в HBufC16 на один символ идет два байта.

Оставить комментарий Add to Memories Tell a Friend

Преобразование Строк в Числа в Symbian C++

[12 November 2009, 12:06]

Преобразование строк в числа в Symbian C++, делается следующим образом.

Создается объект типа TLex, в него можно передать любой дескриптор.
и просто в переменную Val передаем адрес нашего целочисленного параметра.
Обратите внимание, что мы получаем TInt а не int.
Аналогично можно получить и float, double, e.t.c.

HBufC* aPoin = KString().AllocL();
TLex aLex(*aPoin);
TInt a ;
aLex.Val( a);

Оставить комментарий Add to Memories Tell a Friend

Компиляторы,Эмуляторы под Symbian OS: WINSCW, ARMV5 и GCCE

[11 November 2009, 11:44]

У многих, кто только только установил среду разработки Carbide C++ 2.0 и хочет собрать первое приложение возникает вопрос, какой пункт из 5 использовать при сборке.

Пункты мы имеем такие:

1) Winscw udeb
2) ARMV5 - Phone Debug
3) ARMV5 - Phone Release
4) GCCE - Phone debug
5) GCCE - Phone release

Соответственно пойдем по пунктам. Winscw суть собой представялет операционку Symbian, только собранную под Windows. Поэтому, тут вы сможете проверить работоспособность вашего приложения на компьютере. Однако, это не есть Эмулятор Symbian OS(как, например, эмуляторы входящие в состав Java2ME SDK) и вот почему. Под ним вы не сможете запустить ни одно приложение собранное для работы на смартфоне. Об этом впрочем ниже.

Phone debug - Означает сборку, для отладки прямо на мобильному устройстве,
Phone release - Конечный билд приложения для распространения.

Теперь о разнице между ARMV5 и GCCE. Цель у них одна - собрать приложение под архитектуру ARM и Symbian OS: соответственно собранное с ними приложение, вы сможете запустить на смартфоне, но не сможете запустить на ПК.
ARMV5 -> Платный компилятор входящий в состав пакета RealView Development Suite, предназначенный для крупных компаний. Обещается примерно двукратное уменьшение размера исполняемого кода, повышенное быстродействие и.т.п. Более подробно о нем можно почитать на http://www.arm.com
GCCE - бесплатный GNU-компилятор, поддерживаемый сообществом со всеми вытекающими из этого плюсами и минусами. Входит в состав всех S60 SDK.

Разработчикам стоит обратить внимание на 2 вещи:
1) Код успешно компилирующийся под WINSCW не обязательно будет успешно компилироваться под GCCE.
2) При попытке скомпилировать под ARMV5, IDE не сообщит об его отсутствии а выдаст мало-понятный текст об отсутствии файла при сборке.

Оставить комментарий Add to Memories Tell a Friend

Устранение ошибки "Удаленный компьютер отключил сеанс из за ошибки в протоколе лицензирования"

[05 November 2009, 12:41]

После стандартной ситуации когда Windows Terminal Server выдает, что срок действия лицензии истек -> Следует убить ключ HKLM/Software/Microsoft/MSLicensing. Однако в Windows 7, хотя подозреваю и в Vista, после этой операции возникает ошибка "Удаленный компьютер отключил сеанс из за ошибки в протоколе лицензирования"
Соответственно лечится проблема просто, нужно запустить сеанс удаленного подключения от имени администратора.

2 comments Оставить комментарий Add to Memories Tell a Friend

Symbian - Как нарисовать картинку из ресурса

[02 November 2009, 18:07]

Сегодня я расскажу самый простой способ отрисовать заранее подготовленную картинку.
Делается это так:

1) Картинка конвертируется в формат .bmp и кладется в папку gfx

2) Создается (или копируется из примеров) файл bitmaps.mk

Следующего содержания
#
# ==============================================================================
# Name : bitmaps.mk
# Part of : Graphics
# Interface :
# Description :
# Version :
#
# Copyright (c) 2006 Nokia Corporation.
# This material, including documentation and any related
# computer programs, is protected by copyright controlled by
# Nokia Corporation.
# ==============================================================================
#

ifeq (WINS,$(findstring WINS, $(PLATFORM)))
ZDIR=$(EPOCROOT)epoc32\release\$(PLATFORM)\$(CFG)\z
else
ZDIR=$(EPOCROOT)epoc32\data\z
endif

TARGETDIR=$(ZDIR)\private\E1B489E0
ICONTARGETFILENAME=$(TARGETDIR)\GraphicsAppImages.mbm

HEADERDIR=$(EPOCROOT)epoc32\include
HEADERFILENAME=$(HEADERDIR)\GraphicsAppImages.mbg

do_nothing :
@rem do_nothing

MAKMAKE : do_nothing

BLD : do_nothing

CLEAN : do_nothing

LIB : do_nothing

CLEANLIB : do_nothing

RESOURCE :
mifconv $(ICONTARGETFILENAME) /h$(HEADERFILENAME) \
/c24 ..\gfx\image1.bmp /c24 ..\gfx\image2.bmp

FREEZE : do_nothing

SAVESPACE : do_nothing

RELEASABLES :
@echo $(HEADERFILENAME)&& \
@echo $(ICONTARGETFILENAME)

FINAL : do_nothing


ВНИМАНИЕ! Картинки дожны быть в 1 строку и разделяться TAB. Никаких других символов быть недолжно, иначе получим забавный Syntax error. "Did you mean TAB instead of 8 spaces?"

3) Теперь необходимо включить .mk в цепочку сборки. Делается это так: в файл bld.inf заносится строка

gnumakefile bitmaps.mk

4)Добавляем в модуль view. Мы же в нем рисуем, да? :-)
#include
[Error: Irreparable invalid markup ('<graphicsappimages.mbg>') in entry. Owner must fix manually. Raw contents below.]

Сегодня я расскажу самый простой способ отрисовать заранее подготовленную картинку.
Делается это так:

1) Картинка конвертируется в формат .bmp и кладется в папку gfx

2) Создается (или копируется из примеров) файл bitmaps.mk

Следующего содержания
#
# ==============================================================================
# Name : bitmaps.mk
# Part of : Graphics
# Interface :
# Description :
# Version :
#
# Copyright (c) 2006 Nokia Corporation.
# This material, including documentation and any related
# computer programs, is protected by copyright controlled by
# Nokia Corporation.
# ==============================================================================
#

ifeq (WINS,$(findstring WINS, $(PLATFORM)))
ZDIR=$(EPOCROOT)epoc32\release\$(PLATFORM)\$(CFG)\z
else
ZDIR=$(EPOCROOT)epoc32\data\z
endif

TARGETDIR=$(ZDIR)\private\E1B489E0
ICONTARGETFILENAME=$(TARGETDIR)\GraphicsAppImages.mbm

HEADERDIR=$(EPOCROOT)epoc32\include
HEADERFILENAME=$(HEADERDIR)\GraphicsAppImages.mbg

do_nothing :
@rem do_nothing

MAKMAKE : do_nothing

BLD : do_nothing

CLEAN : do_nothing

LIB : do_nothing

CLEANLIB : do_nothing

RESOURCE :
mifconv $(ICONTARGETFILENAME) /h$(HEADERFILENAME) \
/c24 ..\gfx\image1.bmp /c24 ..\gfx\image2.bmp

FREEZE : do_nothing

SAVESPACE : do_nothing

RELEASABLES :
@echo $(HEADERFILENAME)&& \
@echo $(ICONTARGETFILENAME)

FINAL : do_nothing


ВНИМАНИЕ! Картинки дожны быть в 1 строку и разделяться TAB. Никаких других символов быть недолжно, иначе получим забавный Syntax error. "Did you mean TAB instead of 8 spaces?"

3) Теперь необходимо включить .mk в цепочку сборки. Делается это так: в файл bld.inf заносится строка

gnumakefile bitmaps.mk

4)Добавляем в модуль view. Мы же в нем рисуем, да? :-)
#include <GraphicsAppImages.mbg>
Название этого файла взялось из файла .mk, генерируется он автоматом.
5) Объявляем разумеется переменную с картиной как, CFbsBitmap* iBackground;
Теперь самое шикарное. В J2ME мы бы просто загрузили картинку из ресурса. Но тут нас ждет сплошное удивление, для такой, казалось бы, простой задачи:

В .h файле класса View вносим
namespace
{
_LIT ( KMultiBitmapFilename,"GraphicsAppImages.mbm" );
}


В классе View, в ConstructL мы вносим

//"Открываем" интерфейс доступа к файлам
User::LeaveIfError(iFsSession.Connect());
iFsSession.ShareProtected();

//Устанавливаем для filePath значение временной директории
User::LeaveIfError(iFsSession.PrivatePath(filePath));

//Дописываем имя нашего mbm файла
filePath.Append(KMultiBitmapFilename);
//Получаем диск на который установлено приложение
TParsePtrC parse((CEikonEnv::Static()->EikAppUi()->Application())->AppFullName());
//Пример работы со строками, подставляем диск спереди строки
filePath.Insert(0, parse.Drive());
//Открываем Iconprovider - чтобы выдрать картинку из mbm
iIconProvider = new (ELeave) CIconFileProvider(iFsSession, filePath);
//Читаем картинку - ура!
//Последний параметр - номер картинки, берется из приинклюденого выше файла
//на самом деле состоит из EMbmGraphicsappimages+ имя файла с большой буквы без .bmp
iImage1 = AknIconUtils::CreateIconL(*iIconProvider, EMbmGraphicsappimagesImage1);


Соответственно отрисовать картинку можно при помощи gc.BitBlt
Но об этом в следующей истории

Оставить комментарий Add to Memories Tell a Friend

Учимся писать на Symbian C++ с нуля

[08 October 2009, 21:24]

Разработка любой программы на незнакомом языке, где точкой входа не является первая строчка в исполняемом файле, как, например, скриптовые языки php и perl должна начинаться с понимания взаимосвязи работы программы. В Symbian C++ по стандарту создается 5 файлов, а именно

1. .cpp/h
2. Document.cpp/h
3. View.cpp/h
4. Ui.cpp/h
5. Application.cpp/h

Соответственно, согласно документу s_60_programming_games.pdf файл Ui - это файл который контроллирует и обрабатывает нажатия пользователя и передает их во View

View - соответтвенно класс, который содержит движок приложения и отвечает за его отрисовку
Document - должен хранить состояние движка приложения, в современной практике не используется.

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

4 comments Оставить комментарий Add to Memories Tell a Friend

О необходимости проверять количество прочитанных символов

[02 October 2009, 14:22]

Когда я разрабатывал приложения под Windows, или на Php - частенько возникает необходимость читать данные из потока.
На С++ обычно это делается так(синтаксис вызова могу переврать),

unsigned char[] t;
t=new unsigned char[32768];

FileStream fs=new ...;
fs.read(&t);


На J2ME все происходит аналогично. Однако, как правило за всю мою практику буффер всегда заполнялся полностью.
Телефоны Samsung в этом плане исключение. 32кб буфер они заполняют не до конца, в связи с этим когда вы пишите куда-то прочитанные данные - остатки записываются нулями.
Правильно - записывать столько байт, сколько было прочитано в потоке - их количество возвращает функция read.

Оставить комментарий Add to Memories Tell a Friend

Скачка файлов в J2ME

[29 September 2009, 13:03]

Долгое время никак не мог решить одну проблему: скачка файлов в эмуляторе при скорости интернета ~ 100 кб\с выполнялась на уровне 6-7 кб\с. Вначале, я грешил на перерисовку экрана, которую необходимо выполнять для уведомления пользователя о процессе. Однако, дело оказалось в другом. Вот код на скачку предлагаемый многими в интернете(1я ссылка в гугле):
http://www.java2s.com/Code/Java/J2ME/MIDlettofetchapageusinganHttpConnection.htm

while ((ch = is.read()) != -1) {
len = is.available() ;
b.append((char)ch);
}
}
t = new TextBox("hello again....", b.toString(), 1024, 0);
} finally {
is.close();
c.close();
}

display.setCurrent(t);
}

Обратите внимание, чтение из открытого потока идет по одному символу. Но есть же еще функция читающая сразу массив read(bytearray b)

Итак, мой код который реализует скачку на максимально возможной скорости:

byte[] buf=new byte[32768];


while ((is.read(buf)) != -1)
{

BytesRead+=32768;
//os.write(ch);

while(Mode.equals("PAUSE"))
{ Downloads[i].Status=DownloadDesc.PAUSE;
try{Thread.sleep(10000);}catch(Exception ignored){}
}

if(Mode.equals("STOP"))
break;


ticks=System.currentTimeMillis();

if(ticks-previous>=5000)
{
try{
downlspeed=(BytesRead-prevBr)/(ticks/1000-previous/1000);
CurrDownloaded=(StartFrom+BytesRead)/1000+" Kb";
WaitForPaint=true;
mclass.repaint();
while(WaitForPaint);
prevBr=BytesRead;

}
catch(Exception e)
{

}

previous=ticks;
}
if(BytesRead%32768==0)
{
os.write(buf);
os.flush();
// buf.delete(0, buf.length());
Downloads[i].PercentComplete=(StartFrom+BytesRead)/(float)Downloads[i].ByteSize*100;


}
}
os.flush();

Оставить комментарий Add to Memories Tell a Friend

Работа с кодировкой в J2ME

[07 September 2009, 15:54]

Как только деятельность вашего приложения выходит за рамки мобильного телефона, например, в интернет - появляется необходимость работать с различными кодировками.

Однако, работа с ними далеко не всегда тривиальна. На этом примере, хотел бы показать,
как корректно обработать ответ от сервера в UTF-8. Задача усложняется еще и тем, что разбирает ответ компонент kxml - которому для работы обязательно необходим InputStreamReader.
Итак, читаем данные с сервера:
InputStream is = connection.openInputStream();
           InputStreamReader isr=new InputStreamReader(is,"UTF-8");
           StringBuffer InBuf = new StringBuffer();
           int ch;
          
           long len = connection.getLength();
           if(len!=-1)
             { for(int i = 0;i<len;i++)
                   if((ch = isr.read())!= -1)
                       InBuf.append((char)ch);
             }
              else
              {
               while ((ch  = isr.read()) != -1)
                   InBuf.append((char)ch);
              }

           String ServerReply=InBuf.toString();

Тут мы получили данные в виде строки. Кому-то этого может быть уже достаточно, а нам необходимо поместить их в InputStreamReader в правильной кодировке.


            byte[] xmlByteArray = Response.getBytes("UTF-8");
            ByteArrayInputStream xmlStream = new ByteArrayInputStream( xmlByteArray );
            InputStreamReader xmlReader = new InputStreamReader( xmlStream,"UTF-8" );
            XmlParser parser = new XmlParser( xmlReader );

Теперь kxml корректно разберет документ. Вместо UTF-8 справедливо использовать и Windows-1251.

Оставить комментарий Add to Memories Tell a Friend

Обход ограничений Nokia Series 40

[07 September 2009, 13:06]

Сегодня я расскажу о проблеме реализации J2ME в Nokia S40 3rd edition (Nokia 6270 и.т.д.) скачивать файлы размером более 300 кб.

Классическая реализация скачивания предусматривает следующий код:

HttpConnection hc=(HttpConnection)Connector.open("http://www.somehost.com/file.mp4");
hc.setRequestMethod(HttpConnection.GET);
hc.setRequestProperty("Connection", "close");
hc.setRequestProperty("User-agent", System.getProperty("microedition.platform"));
int ResponseCode=hc.getResponseCode();
String ResponseMessage=hc.getResponseMessage();
Downloads[i].ByteSize=Long.parseLong(hc.getHeaderField("Content-Length"))+StartFrom;

Соответственно, в идеале, после этого момента можно открывать поток и производить чтение,
однако добрая нокия выдает ошибку: Error in http operation. После поисков выяснилось, что такой ответ будет на любой файл свыше 300 кб.

Чтобы обойти ограничение сделать нужно вот что. Нужно использовать сокеты и эмулировать протокол HTTP.

Делается это так:
SocketConnection hc=(SocketConnection)Connector.open("socket://"+ServerName+":80");
OutputStream oss=hc.openOutputStream();
oss.write(("GET http://somehost.com/file.mp4 HTTP/1.0\r\n").getBytes());
oss.write(("Host: somehost.com\r\n").getBytes());
oss.write(("Accept: */*\r\n").getBytes());
oss.write(("User-Agent: "+System.getProperty("microedition.platform")+"\r\n\r\n").getBytes());
oss.flush();
oss.close();

И после чего, принять входные данные
InputStream is = hc.openInputStream();
int ch,last_ch=0;
OutputStream os = fc.openOutputStream();
Однако, помимо самих данных будет еще и ответ сервера.
В данном случае, я его просто пропускаю.
while ((ch = is.read()) != -1)
{
if((last_ch=='\n')&&(ch=='\n'))
break;
if((last_ch=='\n')&&(ch=='\r'))
break;
if(ch!=last_ch)
last_ch=ch;

}

Все, казалось бы можно читать данные. Но не тут то было. Выясняется, что неподписанным приложениям запрещен доступ по портам 80,8080,443.
В своем приложении, я переназначил на сервере порт на 9898, при отсутствии такой возможности предлагаю читателю поискать прокси сервер работаюший через отличный от перечисленных порт, и осуществлять коммуникации через него.

Удачной разработки!

Оставить комментарий Add to Memories Tell a Friend

Фанатизм по свободе,

[27 March 2009, 16:18]

Наверное ни для кого, понимающего термин СПО(Свободное программное обеспечение) не секрет, кем является Ричард Столлмен. Недавно он написал статью Ловушка Javascript'a (http://www.gnu.org/philosophy/javascript-trap.html), основной идеей которой является то, что когда код проходит через оптимизатор, убирающий осмысленные названия переменных и методов, заменяющий их одним символом, вычищающий комментарии и убирающий пробелы. Приводится это все на примере Google Docs.
Так вот дядя Столлен нас предупреждает. Нам без нашего ведома всовывают код, который нечитаем человеком, а значит является проприетарным. Более того, он выполняется абсолютно без нашего с вами ведома. Ну и разумеется, предлагает очистить ваше пребывание в интернете от скверны, т.е. использовать, например, Add-on NoScript для FireFox, и еще более забавные, с точки зрения здравого смысла, решения - в свободные браузеры добавить, значит, модуль который будет определять - идеологически правилен ли JavaScript на этом сайте или нет.
А мы же посмотрим на это дело чуть-чуть с другой стороны - философской.
Что есть JavaScript? По сути дела это есть некоторый код, который выполняется у пользователя на компьютере, но не на сервере. Что он представляет из себя, в контексте единого и цельного понятия вэб-приложения, как Google Docs?: Только небольшой кусок кода, который по некоторым причинам выполняется на стороне пользователя. В целом же, значительная часть всего кода обрабатывается именно на сервере... Его идеологическую корректность никто не проверяет.. И более того, я не видел исходников серверной части Google Docs. В этом контексте предложение для каждого JavaScript определять степень свободы, равносильна анализу влияния на безопасность задних стоп-сигналов в машине, с отсутствующими тормозами.

В заключение немного математики,
Без оптимизатора движок кода Google Docs на JavaScript занимает примерно 0.5 Мб.

Давайте возьмем небольшой пример кода на JS и примерно оценим

Код без оптимизатора:
if Peoples.Iam.Hungry()=1 Then
{
Restaurant.Select("ChinaFood").GoForEating();
}
else
{
Hotel.FindNearestHotel().GoSleep();
}
endif;

Суммарно он занимает 165 байт

Код с оптимизатором:
if P.I.H()=1 Then
{
R.S("CF").G();
}
else
{
H.F().S();
}
endif;

Занимает 72 байта.
Экономия траффика более чем в 2 раза.

Так что отчаиваться не стоит. Медицина в наша время и не такое лечит.

Оставить комментарий Add to Memories Tell a Friend

Запускаем xp_cmdshell из под пользователя

[29 November 2007, 14:50]

Я решил помимо жизненных записок еще и публиковать научно-познавательные статьи, которых, увы нет в рунете.

Сегодня поговорим о xp_cmdshell, xp_sqlagent_proxy_account.
Во-первых, если при попытке выполнить xp_cmdshell из под пользователя вы видите
фразу что doenst have permisson. То просто зайдите на сервер через Enterprise Manager,
правой кнопкой нажмите на таблицу, выбирете Manage Permissions... и установите для пользователя права на EXEC.
Если пользователя там нет, то надо в разделе Security/Login установить Доступ для этой БД.

Вторым шагом вы увидите вот это грязное блядство:

xp_cmdshell failed to execute because current security context is not sysadmin and proxy acount is not setup correctly. For more information, refer to Book Online, search for topic related to xp_sqlagent_proxy_account.

Далее по BOL(более идиотских справочников не видел в жизни) предпологается запустить такой запрос

exec master..xp_sqlagent_proxy_account N'SET', N'domain', N'adminlogin', N'adminpass'

Тут начинается самое интересное. При попытке выполнить это дело при установленном SP4 вы увидите
сообщение что "Файл не найден".

Это блядство лечится тем, что вы ищите папку Binn в папке MSSQL там папку Resources
и делаете папку 1049 - точную копию папки 1033 (с теми же файлами)

теперь вроде бы все заебись "Comannd succesfully"
И на 90% систем все работает.
А вот если у вас хуй то выполняйте
EXECUTE msdb..sp_set_sqlagent_properties @sysadmin_only = 0
Этой команды в рунете нет.

Оставить комментарий Add to Memories Tell a Friend

Я хороший PHP программист.

[09 November 2007, 11:38]

Прошел тест. Правда пришлось это делать очень быстро, т.к. начальник стоял над душой.

2 comments Оставить комментарий Add to Memories Tell a Friend

Посудомоечная машина

[08 November 2007, 11:45]

Покупал на выходных посудомойку.

Поскольку стиральная машина у меня BEKO работает отлично, стоит в 2 раза меньше какого-нибудь электролюкса, и у них самая пиздатая реклама которую я в последнее время видел, то выбор был определен.

На нашем рынке есть две модели DFS 1550 и DFN 6610

DFS 1550 внешне скучная и на 9 комплектов. А в 9комплектную посудомойку тяжело класть сковороды и кастрюли. Поэтому выбор пал на 6610.

После поездки в М-Видео на савушкине и попытке там оформить кредит, меня динамили полчаса, пока я ел в местном маке, выяснилось что сегодня кредита не будет так как легла система.

Часа так через четыре когда я пошел в другой м-видео в континенте на богатырском. Она там тоже была но с витрины. Поскольку уже очень хотелось ее купить было дано согласие. И когда я целенаправленно пошел в русский стандарт получать кредит, выяснилось что в ренессансе уже 10 минут как все работает. Кредит был оплачен. Дальше самое интересное.

Эти мудаки от товаров выставленных на витрине коробки хранят не всегда.

Поэтому упаковали они машину в черный вонючий полиэтилен.

Отдельного внимания заслуживает доставка до машины. Подъезжаешь к такому погрузочному отсеку для газели, и думаешь как бы эту хуйню размером со стиральную машину и весом кило 50, спуститьб на метр вниз повернуть и положить в багажник. Грузчики нехотся слезают с постамента и помогают погрузить.

Зато от старых хозяев под раковиной на кухне оказалось все готовым к подключению, так что мастера не пришлось вызывать :)

3 comments Оставить комментарий Add to Memories Tell a Friend

[info]bchgroup

November 2009

S M T W T F S
1234567
891011121314
15161718192021
22232425262728
2930