Сегодня Стив Ласкер (Steve Lasker) в своем блоге анонсировал выпуск SQL Server Compact Edition 3.5 SP1.

  • Появился провайдер SSCE для ADO.NET Entity Framework.
  • Case-sensitive collations
  • Поддержка платформы x64

Ссылки для загрузки:

Previous ArticleNext Article
Технический директор IT-Dimension, компании-разработчика кросс-платформенного программного обеспечения

Leave a Reply

Your email address will not be published. Required fields are marked *

Н.

Настраиваем средства разработки для Windows Mobile (C++/wxWinCE) в Linux

Благодаря стараниям Станислава Блинова у нас появилась возможность разрабатывать ПО для Windows Mobile в Linux, используя компилятор cegcc и библиотеку wxWidgets. О том как настроить средства разработки для Windows Mobile под Linux рассказано в ниже следующей статье:

Захотелось мне тут выяснить, насколько “умерла” бесплатная разработка софта под WinCE. Великий Гугель вывел меня на штуку под названием cegcc – кросс-компилятор, позволяющий собирать WinCE приложения под Линуксом. После возвращения из осадка, в который я выпал, узрев данный инструмент, я решил его проверить на практике.

Проверка прошла успешно – приложения действительно собираются и работают. Правда, местами приходится кое-что править… И тогда захотелось экзотики, а именно – собрать с помощью cegcc библиотеку wxWinCE – порт wxWidgets для WinCE. Сделать это оказалось, мягко говоря, непросто, но все же реально.

В процессе поиска информации по данному вопросу я наткнулся на вот этот пост: http://article.gmane.org/gmane.comp.gnu.cegcc.devel/827. Erik van Pienbroek подкинул отличную шпаргалку. Его патчи действительно встали на ревизию 49149 и после небольшой доработки напильником она собралась. Правда, работала она, мягко говоря, плохо. Рисовала окна как попало, меню размещала вверху окна, само окно, кстати, зачем-то ополовинивала, ну и т.д. Но это уже было что-то.
Потом я умудрился адаптировать (напильник был большой) эти патчи к релизу 2.8.9, т.е. так же собрать сам релиз и получить такую же библиотеку с весьма странным поведеением. И уже только потом стал разбираться, что же не так. Оказалось все достаточно просто – всего лишь правильно указать версию и тип системы… Ну да хватит, как говорится, от слов – к делу!

Далее я опишу способ, как собрать wxWinCE-2.8.9 для PocketPC. Для начала определимся с исходными данными. Система, на которой все это производилось – Debian Lenny:

Linux 2.6.26-1-686 #1 SMP Thu Oct 9 15:18:09 UTC 2008 i686 GNU/Linux

Перечень вещей, которые понадобятся:

  • bison, yacc
  • mingw32ce
  • Bakefile
  • wxWidgets-2.8.9
  • Патч для wxWidgets
  • Файл autogen.mk

Итак, приступим…
Марлезонский балет, часть первая. Установка mingw32-ce.

В принципе, данный процесс достаточно хорошо документирован здесь. Но раз уж мы за это беремся, несколько слов скажу.

  • Если у вас вдруг нету, поставьте bison и yacc (для Debian ставятся через apt-get).
  • Нужно взять с svn текущую версию cegcc:
$ svn co https://cegcc.svn.sourceforge.net/svnroot/cegcc/trunk/cegcc cegcc

Когда скачается, в текущей директории появится директория cegcc.

$ cd cegcc/src
$ mkdir build-mingw32ce

Собирать в корне исходников скрипт не даст, сам попросит создать директорию.

$ cd build-mingw32ce
$ sh ../build-mingw32ce.sh

Все, пошла сборка (и установка). По умолчанию компилятор встанет в /opt/mingw32ce. Этот путь можно поменять с помощью опции --prefix к скрипту (например ../build-mingw32ce.sh --prefix=/my/super/puper/dir/mgwce)

После установки компилятора добавьте /opt/mingw32ce/bin (соответственно, если вы не меняли префикс) в PATH. На Debian это можно сделать в /etc/profile.

С компилятором все, переходим ко второй части балета.

Сборка wxWinCE

  1. Нам понадобится Bakefile. Если его нет (или если он древнее, чем 2.3.0) – взять можно на www.bakefile.org. Эта утилита будет новые Makefile’ы создавать.
  2. Теперь надо скачать архив wxWidgets-2.8.9 и куда-нибудь его распаковать. Все остальные действия надо производить, находясь в директории wxWidgets-2.8.9. (Здесь и далее на скриншотах зеленым выделены моменты, на которые стоит обратить внимание).
  3. tar xzf wxWidgets-2.8.9.tar.gz
  4. Прилагаемый файл autogen.mk помещается в директорию build. Затем можно применить патч.
  5. cp /home/capricorn/work/articles/mingw32ce-wxWinCE/autogen.mk build
    patch -p0 /home/capricorn/work/articles/mingw32ce-wxWinCE/wxWinCE.patch-2
    
  6. Немного поправим WinCE SDK, а именно – файл /opt/mingw32ce/arm-mingw32ce/include/aygshell.h. Нужно добавить в него следующие строки:
    #define COMCTL32_VERSION 0x020e
    #define SHA_INPUTDIALOG  0x00000001
    #define GN_CONTEXTMENU   1000
    #define SHRG_RETURNCMD   0x00000001
    

    Эти определения присутствуют в “родном” aygshell.h из Windows Mobile 5.0 SDK. При желании можете посмотреть, где точно они располагаются в этом файле, и добавить их в те же места.

  7. Этот шаг необходимо выполнить, если Bakefile у вас не 2.3.0 (здесь я отметил файлы, которые должны быть заменены). Путь /usr/local/share/aclocal, естественно, действителен для Debian. На другой системе может быть другим.

    cp /usr/local/share/aclocal/bakefile* build/aclocal
    
  8. Теперь нужно создать новые билд-скрипты

    ./autogen.sh && make -f build/autogen.mk
    

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

  9. Выполнение этого шага сконфигурирует среду на сборку статической монолитной библиотеки с поддержкой юникода. Опция --prefix нужна, чтобы указать, куда впоследствии будет инсталлироваться wxWinCE. Поскольку mingw32ce у меня лег в /opt, wxWinCE я решил положить рядышком, так что я выбрал --prefix=/opt/wxWinCE-2.8.9:

    По завершении конфигурации вы должны получить такую картину:
  10. Теперь остается только выполнить $ make И можно смело идти пить кофе. Когда же, наконец-таки, все будет собрано, останется только проинсталлировать:
    $ sudo make install
    

    Последний шаг нужно выполнять от имени root’а (если только вы не поставили в --prefix директорию, в которую вам разрешена запись). Так что – либо sudo, либо su.

    Вот и все. Теперь можно смело собирать сэмплы или свои собственные приложения. Для получения флагов компилятора не забывайте использовать <prefix>/bin/wx-config. Примерно таким же образом можно собрать и динамическую, и debug библиотеку (см. configure --help). Вот только чтобы собрать wxWinCE для смартфона надо руками править configure. К сожалению, я не спец по autotools. То, что было необходимо подправить – догадался, откопал, подсмотрел… А по-хорошему надо бы дописать строчки в configure.in, чтобы после autogen скрипт configure позволял бы с помощью опций указать версию WinMobile и тип платформы. Но это уже будет, видимо, другая история…

Д.

Доступ к базам данных MySQL из приложений для Palm WebOS

Доступ к базам данных – очень востребованный функционал приложений. И в этот раз мы рассмотрим способ для WebOS приложений получить данные из базы данных MySQL, находящейся на удаленном сервере.

Для начала создадим новое приложение и в нем новую сцену с названием Main. Как создать проект и сцену можно узнать из этой статьи.

Затем добавим в созданную сцену список:

views/main/main-scene.html

<div class="palm-group">
  <div class="palm-group-title" id="sample-toggle">
  	<span x-mojo-loc="">Database Content</span></div>
    <div class="palm-list">
       <div id="dbList" x-mojo-element='List'></div>
    </div>
  </div>
</div>

Для нашего списка нам необходимо определить HTML-шаблон элементов списка:
views/main/dbItemTemplate.html

<div class="palm-row" x-mojo-tap-highlight="momentary">
  <div id="nameField">#{Name} (#{Year})</div>
</div>

В шаблоне указано, что если в элементе списка есть свойства Name и Year, то они должны быть отображены.

Теперь в assistants/main-assistant.js внесем необходимые изменения для того, чтобы виджет-список создался при запуске:

function MainAssistant() {
}

MainAssistant.prototype.setup = function() {
this.count = 0;
this.dbListModel = {};
this.controller.setupWidget("dbList",
        {
            itemTemplate: "main/dbItemTemplate"
        },
        this.dbListModel);
}

Как видно из кода, в атрибутах виджета мы указываем шаблон элементов main/dbItemTemplate. Название должно совпадать с названием ранее созданного HTML-файла с описанием шаблона элементов.

После всех манипуляций, описанных выше, у нас должно получиться что-то подобное:

WebOS Empty List

Отлично, с GUI мы закончили, теперь займемся получением данных с сервера.

Для начала создадим базу данных и в ней таблицу, из которой мы будем получать записи и отображать их на форме:

CREATE TABLE remote_data(
 ID INTEGER NOT NULL AUTO_INCREMENT ,
 Name VARCHAR( 32 ) NOT NULL ,
 Year SMALLINT NOT NULL ,
 PRIMARY KEY ( ID )
);

Затем создадим PHP-скрипт, который будет получать данные из таблицы и выдавать их в формате JSON:

<?php
header('Content-type: application/json');
$dbhost = "localhost";
$dbuser = "root";
$dbpass = "";
$dbname = "webos_test";
$link = mysql_connect($dbhost, $dbuser, $dbpass)
    or die('Could not connect: ' . mysql_error());
mysql_select_db($dbname) or die('Could not select database');

switch($_POST['operation'])
{
 case 'getResults':
 {
  $table = $_POST['table'];
  $query = sprintf("SELECT * FROM %s", mysql_real_escape_string($table));
  $result = mysql_query($query) or die('Query failed: ' . mysql_error());
  $all_recs = array();
  while ($line = mysql_fetch_array($result, MYSQL_ASSOC))
  {
   $all_recs[] = $line;
  }
  break;
 }
}
echo json_encode($all_recs);
mysql_free_result($result);
mysql_close($link);
?>

Что делает этот скрипт:

  • Получает из POST-параметров название операции, непример getResults.
  • Если операция поддерживается, то получает из POST-параметров имя таблицы
  • Получает записи из таблицы в массив
  • Конвертирует в JSON и отдает клиенту

В результате у нас в выдаче должно получиться что-то подобное:

[
 {"ID":"1","Name":"Test 1","Year":"2008"},
 {"ID":"2","Name":"Test 2","Year":"2009"},
 {"ID":"3","Name":"Test 3","Year":"2010"}
]

Теперь нам надо научить наше WebOS приложение получать эти данные с сервера.

Для получения данных в приложении нам необходимо выполнить AJAX-запрос на сервер. Для этого используется метода Ajax.Request():

MainAssistant.prototype.getRemoteData = function(table) {
    var url = 'http://192.168.0.1/remote-data.php';
    try
    {
        if(!table)
        {
            throw('getRemoteData(): You should specify database table name');
        }
        var request = new Ajax.Request(url,
        	{
            	method: 'post',
            	parameters: {'operation': 'getResults', 'table': table},
            	evalJSON: 'true',
            	onSuccess: this.getRemoteDataSuccess.bind(this),
            	onFailure: function()
            	{
                	Mojo.Log.error('Failed to get Ajax response');
            	}
        	});
    }
    catch(e)
    {
        Mojo.log.error(e);
    }
}

В исходном коде указан IP адрес машины в локальной сети. Если вы тестируете приложение на эмуляторе, а сервер со скриптом и базой данных находится в Internet, то, скорее всего, доступа к серверу у вас по умолчанию не будет. Для того, чтобы разрешить эмулятору ходить в сеть, надо в настройках LAN-соединения разрешить доступ из подсети VirtualBox:
Share Internet with WebOS Emulator

Итак, в приведенном выше коде указано, что при успешном завершении запроса необходимо вызвать метод getRemoteDataSuccess(). В этом методе мы должны преобразовать полученный ответ от сервера в массив и обновить список. Делается это следующим образом:

MainAssistant.prototype.getRemoteDataSuccess = function(response) {

 	try
 	{
 		this.dbListModel.items = response.responseText.evalJSON();
 		this.controller.modelChanged(this.dbListModel);
 	}
 	catch(e)
 	{
 		Mojo.log.error(e);
 	}
}

Для преобразования JSON-строки в массив мы использовали метод evalJSON(), а для того чтобы виджет обновил список элементов мы вызвали метод modelChanged() объекта-контроллера.

Все это чудесно, научили приложение делать запрос к серверу и обрабатывать результаты, но если мы запустим приложение, то ничего не произойдет. А все потому что мы не указали, когда должен вызываться метод getRemoteData().

Вызвать этот метод можно при запуске приложения. У класса сцены есть метод, который отрабатывает, когда сцена загружена. Это метод ready(). Вот в нем мы и запустим выполнение AJAX-запроса:

MainAssistant.prototype.ready = function() {
this.getRemoteData('remote_data');
}

И вот, после запуска увидим такое:

WebOS List Loaded from MySQL Database

На этом все.

Скачать исходный код демонстрационного приложения.