ПРОГРАММИРОВАНИЕ    НА    V I S U A L   C + +
РАССЫЛКА САЙТА       
RSDN.RU  

    Выпуск No. 77 от 26 мая 2002 г.

РАССЫЛКА ЯВЛЯЕТСЯ ЧАСТЬЮ ПРОЕКТА RSDN , НА САЙТЕ КОТОРОГО ВСЕГДА МОЖНО НАЙТИ ВСЮ НЕОБХОДИМУЮ РАЗРАБОТЧИКУ ИНФОРМАЦИЮ, СТАТЬИ, ФОРУМЫ, РЕСУРСЫ, ПОЛНЫЙ АРХИВ ПРЕДЫДУЩИХ ВЫПУСКОВ РАССЫЛКИ И МНОГОЕ ДРУГОЕ.

Здравствуйте, уважаемые подписчики!


 НОВОСТИ

Shared Source CLI - открытая версия .Net от Microsoft

В конце марта на сайте Microsoft появился архив под длинным названием Shared Source Common Language Infrastructure (CLI) Implementation Beta (кодовое название Rotor). В его описании (что не характерно для сайта Microsoft) часто мелькает название FreeBSD, а также навевающий ассоциации со свободно распространяемым ПО термин Shared Source. Этот архив - ни что иное, как усеченный вариант .Net CLR, который был изменен Microsoft в целях переносимости. Что же все это значит?

Shared Source - это новый подход Microsoft к распространению программного обеспечения. Очевидно, что эта программа появилась под натиском все усиливающихся сообществ разработчиков ПО с открытым кодом. В рамках Shared Source Microsoft позволяет скачать и использовать исходные коды некоторых своих разработок. К сожалению, документ The Microsoft Shared Source Philosophy, который должен объяснить суть программы, никаких конкретных слов не содержит. Он просто говорит, что Open Source - это плохо, а Shared Source - хорошо.

Но политика распространения кода - это одно, а сам код - другое. Код доступен кому угодно в виде 11-мегабайтного tgz-файла. Сейчас CLI работает под Windows XP и FreeBSD, но в будущем возможно появление версий и для других платформ. Главное достоинство CLI - он содержит большую часть исходных кодов библиотек .Net. В интернете уже появились сообщения, что CLI можно собрать под W2k и другими ОС Microsoft. Впрочем, было бы странно, если бы код, предназначеный для портирования на другие платформы, нельзя было перенести на родные платформы.

Shared Source Common Language Infrastructure (CLI) Implementation - это исходный код работающей реализации стандартов ECMA-334 (C#) и ECMA-335, описывающего инфраструктуру Common Language Infrastructure, аналогичную CLR, используемой в .NET Framework (www.ecma.org).

Архив CLI в форме исходного кода содержит:

  • Реализацию runtime CLI (ECMA-335).
  • Компиляторы C# (ECMA-334) и JScript, работающие с CLI.
  • Средства разработки для CLI - ассемблер/дизассемблер языка MSIL (ilasm, ildasm), отладчик (cordbg), утилиту для просмотра метаданных (metainfo) и другие утилиты.
  • Слой адаптации к платформе (Platform Adaptation Layer, PAL), обеспечивающий работоспособность CLI на FreeBSD.
  • Средства для сборки проектов (nmake, build и др.).
  • Документацию.
  • Тестовые средства.

Сам Microsoft заявляет, что Rotor не является переносом .Net на другую платформу, и что в реализациях CLI и CLR существуют значительные различия. Ключевым словом здесь является <различия>. Кроме того, пока что CLI существует только в бета-версии. Сроки выхода следующих бета-версий и окончательной версии не называются. Несмотря на заверения разработчиков в стабильности работы кода, на данном этапе применение его в реальных проектах сомнительно. Но это и не важно. Главное, при затруднениях в .Net-разработке можно посмотреть, как что устроено и обойти подводные камни.

Чтобы перенести Windows-приложение на другую платформу, нужно перенести Win32 API, чтобы перенести COM - нужно перенести Win32 API и COM API, ну, а чтобы перенести .Net - нужно перенести Win32 API, COM API и .Net. Нам трудно судить, получилась ли эта шутка смешной, но MS, хотя и частично, воплотила ее в жизнь. Для переносимости был создан PAL (Platform Adaptation Layer), набор динамически подключаемых библиотек, реализующий основные функции Win32 и COM API (242 функции), используемые в CLI. PAL аналогичен Apache Portable Runtime (APR). Теоретически, перенос Rotor на другую ОС должен сводиться исключительно к переносу PAL. PAL позволяет реализовать:

  • Создание и уничтожение контекстов приложений.
  • Отладку и поддержку средств разработки.
  • Работу с потоками и управление памятью.
  • Исключения.
  • Локали.
  • Операции синхронного файлового ввода/вывода.
  • Операции асинхронного сетевого ввода/вывода.
  • Критические секции, мьютексы, семафоры и события в стиле Win32.
  • Работу с локальным COM.

Первая версия Rotor компилируется под Windows XP и FreeBSD 4.5. Кроме огромного количества памяти, для ее работы потребуется Perl. FreeBSD, как правило, содержит Perl, а под Windows дело обстоит хуже. Большинству желающих придется скачать Perl с сайта ActiveState. Пользователям Windows понадобится и Visual Studio .NET (или другой компилятор C/C++, а так же время на адаптацию кода под него), так как наличия .NET Framework SDK недостаточно для Rotor.

В развернутом виде Rotor занимает около 70 МБ. Однако после компиляции это добро займет полгигабайта под Windows, и около гигабайта - под FreeBSD. 24 МБ из них - это исходные коды библиотек, входящих в .Net, написанных на С#. Остальное - это в основном исходники на С++ и make-файлы. Это позволяет сказать, что основная часть .Net написана на С++.

Подробные инструкции по установке и начальным шагам использования Rotor можно найти в статьях Dave Stutz и Brian Jepson на www.oreillynet.com.

Практическая ценность CLI, то есть применимость в реальных приложениях, пока не очень понятна. Однако в Shared Source CLI много интересного для разработчика. Например, разработчики, которым интересно, что у .Net внутри, могут посмотреть на реализации сборки мусора, JIT-компиляции, протоколов безопасности, организацию среды и систем виртуальных объектов.

Но, если рассматривать CLI с точки зрения противостояния .Net-Java, это очень сильный ход Microsoft. Он если и не выбьет из рук оппонентов доводы о <непереносимости> и закрытости продуктов Microsoft, то значительно ослабит их.

MS заявляет, что Shared Source CLI может представить значительный интерес для академических и образовательных учреждений, так как на его основе легко организовать учебный курс по современным компиляторам или JIT-оптимизации. Но это лукавство. Дело в том, что многие университеты уже выбрали Яву для своих учебных программ. Главным их доводом было отсуствие исходного кода в .Net, не позволяющее студентам и преподавателям углубиться в изучаемую проблему на только ими определяемую глубину.

Еще одна категория разработчиков, которой может пригодиться CLI - энтузиасты переноса .Net на другие платформы. Лично я знаю только одного такого, но догадываюсь, что их может быть несколько. Для них CLI - это подарок судьбы, руководство к действию и эталонная реализация в одном флаконе.


 ВОПРОС-ОТВЕТ

Как выдать окно выбора каталога?

Windows Shell API включает функцию SHBrowseForFolder, которая отображает стандартный диалог, с помощью которого пользователь может выбрать нужный каталог. На самом деле, выбрать можно не только каталог, а любой объект Shell namespace, в том числе принтеры и компьютеры. Ниже приведён пример использования этой функции:


#include <windows.h>
#include <shlobj.h>
#pragma comment(lib,"shell32")

bool GetFolder (LPTSTR szPath)
{
    szPath[0] = 0;
    bool result = false;
    
    LPMALLOC pMalloc;
    if (::SHGetMalloc(&pMalloc) == NOERROR) {
        BROWSEINFO bi;
        ::ZeroMemory(&bi,sizeof bi);
        bi.ulFlags = BIF_RETURNONLYFSDIRS;
        LPITEMIDLIST pidl = ::SHBrowseForFolder(&bi);
        if (pidl != NULL) {
            if (::SHGetPathFromIDList(pidl,szPath))
                result = true;
            pMalloc->Free(pidl);
        }
        pMalloc->Release();
    }
    return result;
}

Хотя наша функция и делает то, что нам нужно, но, скорее всего, вы найдёте её возможности слишком скромными. С другой стороны возможности функции ::SHBrowseForFolder позволяют добавить следующую функциональность:

  • Установка дескриптора окна-владельца диалога.
  • Добавление заголовка к диалогу.
  • Отображение текущего каталога.
  • Установка каталога по умолчанию.
  • Установка корневого каталога.

Я не вижу причин не использовать эти возможности. Изменим нашу функцию.


#include <windows.h>
#include <atlbase.h>
#include <shlobj.h>
#pragma comment(lib,"shell32")

static int CALLBACK
BrowseCallbackProc (HWND hWnd, UINT uMsg, LPARAM lParam, LPARAM lpData)
{
    TCHAR szPath[_MAX_PATH];
    switch (uMsg) {
    case BFFM_INITIALIZED:
        if (lpData)
            SendMessage(hWnd,BFFM_SETSELECTION,TRUE,lpData);
        break;
    case BFFM_SELCHANGED:
        SHGetPathFromIDList(LPITEMIDLIST(lParam),szPath);
        SendMessage(hWnd, BFFM_SETSTATUSTEXT, NULL, LPARAM(szPath));
        break;
    }
    return ;
}

BOOL GetFolder (LPCTSTR szTitle, LPTSTR szPath, LPCTSTR szRoot, HWND hWndOwner)
{
    if (szPath == NULL)
        return false;

    bool result = false;

    LPMALLOC pMalloc;
    if (::SHGetMalloc(&pMalloc) == NOERROR) {
        BROWSEINFO bi;
        ::ZeroMemory(&bi,sizeof bi);
        bi.ulFlags   = BIF_RETURNONLYFSDIRS;

        
        bi.hwndOwner = hWndOwner;

        
        bi.lpszTitle = szTitle;

        
        bi.lpfn      = BrowseCallbackProc;
        bi.ulFlags  |= BIF_STATUSTEXT;

        
        bi.lParam    = LPARAM(szPath);

        
        if (szRoot != NULL) {
            IShellFolder *pDF;
            if (SHGetDesktopFolder(&pDF) == NOERROR) {
                LPITEMIDLIST pIdl = NULL;
                ULONG        chEaten;
                ULONG        dwAttributes;

                USES_CONVERSION;
                LPOLESTR oleStr = T2OLE(szRoot);

                pDF->ParseDisplayName(NULL,NULL,oleStr,&chEaten,&pIdl,&dwAttributes);
                pDF->Release();

                bi.pidlRoot = pIdl;
            }
        }

        LPITEMIDLIST pidl = ::SHBrowseForFolder(&bi);
        if (pidl != NULL) {
            if (::SHGetPathFromIDList(pidl,szPath))
                result = true;
            pMalloc->Free(pidl);
        }
        if (bi.pidlRoot != NULL)
            pMalloc->Free(bi.pidlRoot);
        pMalloc->Release();
    }
    return result;
}

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


BOOL GetFolder(LPCTSTR szTitle,LPTSTR szPath,LPCTSTR szRoot=NULL,HWND hWndOwner=NULL);

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


Это все на сегодня. Пока!

Алекс Jenter   jenter@rsdn.ru
Duisburg, 2001.    Публикуемые в рассылке материалы принадлежат сайту RSDN.

| Предыдущие выпуски     | Статистика рассылки