dot42 — компилятор C# для Dalvik Runtime

    Главным недостатком Mono для Android является то, что для работы приложений требуется отдельная среда выполнения, отличная от Dalvik. И хотя полный доступ к CLR выглядит весьма привлекательно, проксирование и маршаллинг вызовов от одной среды выполнения к другой могут сильно повлиять на производительность. Так почему бы не убрать промежуточную компиляцию в IL-код и получать сразу рабочий Dex-код? Этим и занимается проект dot42.



    В январе, после 1 года разработки, авторы проекта dot42 наконец-то перешли от обещаний к пряникам. И, хотя проект еще не дотягивает до состояния боевого продукта-конкурента Mono, стоит, как минимум, его рассмотреть и попробовать.

    Признаюсь, я немного слукавил, сказав, что компилятор dot42 «убирает» IL-код. Это не совсем так. Вместо этого он читает IL-код и конвертирует его в новый язык Register Language или, если короче, RL. Главная разница между IL и RL в том, что IL-код работает на стековой модели выполнения (как и байт-код у Java), а RL-код на регистровой, так же как Dalvik. После получения RL-кода, dot42 производит ряд оптимизаций и наступает этап финальной компиляции. Именно после последнего этапа и получается dex-код, язык среды Dalvik. В чем отличие RL от Dex написано в самом первом посте в блоге разработчиков.

    На каждом этапе работы компилятора оригинальная дебаг-информация сохраняется, разумеется, компилятору приходится конвертировать ее из формата PDB в дебаг-формат для dex-кода. dot42 использует adb (Android Debug Bridge) для подключения отладчика в Visual Studio.

    После компиляции библиотеки Android'а используются напрямую. Компилятор понимает большинство типов, например, java.lang.Boolean сопоставляется с System.Nullable<bool>. Правда, кое-какие телодвижения с типами данных все-таки придется сделать. Поскольку dot42 оперирует непосредственно с dex-кодом, есть несколько ограничений на функции и возможности C# и .NET. Пожалуй самое главное из них — это отсутствие пользовательских value-типов (структур). В виртуальной машине Dalvik просто нет поддержки таких типов, поэтому и сопоставить структуры никак не получится.

    Частый вопрос при использовании dot42: какие структуры данных использовать, .NET или Android? Например, что использовать, System.Collections.Generic.List<T> или java.util.ArrayList<E>? Один из разработчиков dot42, Ewout Prangsma, советует отдавать предпочтение Java-классам. Даже несмотря на то, что List<T> — тонкая надстройка над ArrayList<E>, это по-прежнему дополнительный код, который необходимо будет включить в сборку и выполнять в дальнейшем.

    dot42 — коммерческий продукт (профессиональная версия стоит 399 $), однако, существует Community License, позволяющая не только протестировать продукт, но и опубликовать готовые приложения в Google.Play и аналогичных магазинах. Правда, публикуемые таким образом приложения должны быть бесплатны.

    Попробуем?


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

    После установки, можно поиграться с примерами из Samples.zip в корневой директории dot42. Так же есть Hello World Tutorial.

    У меня не получилось подключить свой HTC One X (с прошивкой Jelly Bean) в Device Center, поэтому я создал новый эмулятор, с теми же программными характеристиками:


    Создал проект, все как в Hello World Tutorial. Запустил в виртуальной машине и все действительно заработало:



    К сожалению, заявленная поддержка отладки пока хромает. Visual Studio 2012 после любых махинаций с дебагом просто падает и предлагает перезапустить себя. Попробовать на 2010 у меня нет возможности. В любом случае, я думаю, что это временное явление.

    Кстати, на реальном устройстве все выглядит примерно так же:


    В общем, лично я с интересом буду следить за проектом. :o)

    Если вы видите какие-то ошибки, пожалуйста, сообщите о них в пм.

    UPD.
    Судя по сообщению в твиттере хабраэффект был. :-)
    @dot42news For our Russian followers: http://habrahabr.ru/post/168689/
    Поделиться публикацией
    AdBlock похитил этот баннер, но баннеры не зубы — отрастут

    Подробнее
    Реклама
    Комментарии 48
    • +12
      Кто проведет сравнение производительности java и данного продукта на вычислительных задачах, тому плюс в карму и одобрение.
      • +5
        Я боюсь вызвать ваше личное неодобрение, но так в лоб сравнивать две виртуальные машины не стоит. Не так важно какая из них самая эффективная числомолотилка. Разница будет в пределах погрешности и зависеть даже от конкретной архитектуры процессора.
        Тут скорее интересны печеньки идущие в комплекте: WCF, готовые сниппеты и паттерны, портабельность, реюзабельность имеющегося кода — т.е. скорость разработки, а не скорость работы.
        • +9
          Коллега, вы не поняли. Получаемый apk выполняется на той же виртуальной машине Dalvik, что и java.
          Предположу, что crmMaster хочет понять, как сильно проседает производительность (и память!) при такой компиляции. И тут я с ним на 100% соглашусь — это очень важный момент, т.к. такая компиляция может выдавать результаты хуже, чем существующий Mono.

          Кстати, Dex2Jar и немного магии jd-gui...
      • –7
        Объясните мне пожалуйста. Для чего вообще все это надо? Неужели только из-за синтаксического сахара который присутствует в последних версиях C#?
        Или «нельзя так просто взять» и писать на Java?
        • +17
          «Во-первых, это красиво».

          А если серьёзно, то представьте ситуацию, где ядро написано на C#, постоянно развивается и используется в множестве проектов. И Android-приложение — всего лишь одно из них. Переписывать для него ядро постоянно на Java — мартышкин труд.
          • +14
            Спасибо. Это действительно аргумент.
          • +5
            C# обеспечивает чудесную кроссплатформенность. При чем на некоторых платформах он является безальтернативным вариантом (PS Vita, XBox). В основном это актуально для игр.
            Но да, сам использую и другим советую именно mono. Так как
            отсутствие пользовательских value-типов (структур)
            удар по производительности (особенно для игр)
            • +3
              C# обеспечивает чудесную кроссплатформенность.


              Ага, благодаря #if .. #endif его даже в JavaScript можно транслировать, при этом имея рабочую .NET версию (и это активно используется в нашем проекте).
              • +5
                JSIL еще круче — там просто целые игры на XNA можно портировать на JS, причем в отличии от Script# не нужно писать на специальном диалекте C# со своей BCL. Сайт: JSIL.org
                • 0
                  Я смотрел сравнение этих фреймворков и выбрал ScriptSharp, потому что JSIL работает уже с готовыми сборками или проектом и не интегрируется со студией. Ну и из-за специального диалекта генерируется более чистый JavaScript код.

                  Хотя JSIL тоже надо бы попробовать.
            • +2
              Многоплатформенность. У нас продукт на C# пишется для Винды, Айпада и планшетов на Андроиде. Не будь Си шарпа на этих трёх платформах, пришлось бы держать три штата программистов на трёх языках.
              • +1
                Без этого синтаксического сахара в Java жизнь больше не мила…
              • +4
                Может кому нибудь будет интересно
                blog.xamarin.com/android-in-c-sharp/
                • +1
                  А за WCF-сервис можно с ним быстро зацепиться?
                  • 0
                    Если оно и клиентскую сборку WCF сожет перевести в dex, то почему бы и нет
                  • +1
                    О просто замечательно. Однозначно в закладки. Спасибо за статью.
                    • 0
                      Т.е. какие-то сторонние сборки использовать не получится? (Самый тупой пример: MySql.Data.dll)
                      • +2
                        Если они не используют структур, то должно получиться…
                        • 0
                          Да, но никто не пишет сборки специально так, чтобы не было структур :)
                          • +1
                            Пишут. Структуру невозможно использовать так же свободно, как и класс.

                            Вопрос: при каких условиях код ниже не скомпилируется? Известно, все требуемые свойства существуют и доступны, все типы соответствуют.
                            dict[key].Foo = 42;

                            Ответ: Если dict[key] — структура.
                            • 0
                              > Пишут. Структуру невозможно использовать так же свободно, как и класс.

                              То, что «если лучше подходит класс, используйте класс» — совсем другой вопрос.

                              Тут интересны библиотеки, в документации для разработчиков которых сказано, что структуры использовать нельзя.
                      • 0
                        Здравствуйте, поясните нубу: писать всё равно приходится на java со всеми android'ными прелестями типа слоёв, ресурсов, провайдеров? Просто теперь появилась возможность писать в другой IDE? Собственно в студии. Или я ошибаюсь?
                        • +2
                          Структуры — одно из главных преимуществ C# перед Java. Выпиливаем их, и теперь не понятно зачем нужен такой C#. Короче говоря, Mono пока вне конкуренции.
                          • +8
                            Главный с точки зрения производительности (вы ещё забыли runtime generics) но ведь в C# ещё много языковых плюшек, отсутсвующих в JAVA (лямбды, замыкания, события, свойства и т.п.)
                            • –8
                              много языковых плюшек, отсутсвующих в JAVA (лямбды, замыкания, события, свойства и т.п.)

                              но зачем это всё нужно?
                              анонимные функции в java с версии 8 есть
                              • –1
                                Затем что с событиями очень легко и удобно работать. Свойства показывают уникальное для класса значение, через переменную просто так этого не сделаешь. Плюс прибиндить её (переменную) к интерфейсу извратиться нужно.А без замыканий, мы уходим от ооп к функциональщине, чего лично я вообще не люблю.
                                • –2
                                  с событиями очень легко и удобно работать

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

                                  что это значит? что такое уникальное значение? uuid?
                                  прибиндить её (переменную) к интерфейсу

                                  Вы не понимаете смысла интерфейса
                                  без замыканий, мы уходим от ооп к функциональщине,

                                  image
                                  • –2
                                    1) ds.DataContextChanged += new DependencyPropertyChangedEventHandler(ds_DataContextChanged);
                                    Подписались и в дальнейшем при каждой смене датаконтекста у нас будет запуск нужного метода

                                    Второй пример

                                    RefreshSuite.Invoke(this,property);

                                    Обновление может вызываться неявного от клиента (ну значение текстбокса изменил, или кнопочку нажал), А может явно, если еще другой пользователь в другой стране нажал, пользователь сидит и мониторит когда ж он нажмет.
                                    Если в джаве неудобно работать с евентами, то откуда вы решили что в шарпе с ними же так же туго?

                                    2)
                                    уникальное для класса значение.
                                    Не так выразился. Сам виноват, но все ж у свойств есть преимущество перед переменными класса в том что когда устанавливается значение можно завесить на него вызов события какого нибудь («Property Changed» например)
                                    Пример из текущего проекта:

                                    public DomainDataSource DS { get { return _ds; } set { if (_ds != null) _ds.DataContextChanged -= new DependencyPropertyChangedEventHandler(ds_DataContextChanged); _ds = value; fbrEdit.ds = value; if (_ds != null) _ds.DataContextChanged += new DependencyPropertyChangedEventHandler(ds_DataContextChanged); } }

                                    3) Ладно, раз я не понимаю смысла интерфейса, расскажите мне не понимающему как вы реализуете блокировку/видимость компонентов отображения от внутренного состояния класса? Чур метод для обхода все компонентов не предлагать.
                                    4) Замыкания. Открываем вики, читаем подряд два абзаца
                                    Функциональное программирование предполагает обходиться вычислением результатов функций от исходных данных и результатов других функций, и не предполагает явного хранения состояния программы.

                                    И второй
                                    Противопоставляется парадигме императивного программирования, которая описывает процесс вычислений как последовательное изменение состояний (в значении, подобном таковому в теории автоматов).


                                    P.S. и там ниже подсказывают еще про плюсы c# LINQ. Вот уж с этим спорить не будете?
                                    • +1
                                      ) ds.DataContextChanged += new DependencyPropertyChangedEventHandler(ds_DataContextChanged);

                                      ds.onDataContextChanged(new DependencyPropertyChangedEventHandler(ds_DataContextChanged));
                                      в java
                                      2)

                                      написал выше
                                      как вы реализуете блокировку/видимость компонентов отображения от внутренного состояния класса?

                                      public int getSomeInt()
                                      {
                                      if (!canIGetThisInt)
                                      throw new InvalidAccessException();
                                      else
                                      return someInt;
                                      }
                                      4)

                                      тоесть, яп без замыканий == функциональный?
                                      • –2
                                        2) То есть
                                        public int getSomeInt()
                                        {
                                        if (!canIGetThisInt)
                                        throw new InvalidAccessException();
                                        else 
                                        return someInt;
                                        }
                                        

                                        Быстрее и проще чем
                                        Value="{Binding Path=supplier,Mode=OneWay}"
                                        


                                        Плюс еще и ексепшен, а если там не должно быть этого значения? Ну просто нал вернуло? Будете все эти ексепшены руками обрабатывать?
                                        4) Нет, я этого и не говорил, не передергивайте слова. Я сказал что мы уходим от ооп к функциональщине, имея ввиду что стиль становиться похожим на функциональное программирование. И пожалуйста объясните свое мнение что вы подразумеваете под функциональным программированием.
                                        • +1
                                          синтаксический сахар
                                          в c# что произойдёт, если там не должно быть значения?
                                          4)
                                          моё мнение такого, что слова «отсутствие замыканий» и «функциональное программирование» никак не коррелируют
                                          и да
                                          linq for java
                                          • –2
                                            Ексепшена не будет просто будет пустота вместо значения.
                                            4) то есть вы считаете что изменение свойства объекта методом этого же объекта никак не пересекается с приведенным выше утверждениями?
                                            • +1
                                              пустота вместо значения.

                                              что такое «пустота»? я знаю два значения памяти внутри компьютера 0 или 1, что такое «пусто»? null это не пусто, кстати
                                              да, изменение свойств объекта методом этого объекта — нормальное явление, сеттеры, например, это они и есть
                                              а замыкания, это просто проброс внешней переменной внутрь функции объявленной внутри другой функции, очевидно, в java 8 это есть

                                        • 0
                                          ds.DataContextChanged += new DependencyPropertyChangedEventHandler(ds_DataContextChanged);

                                          Неудачный пример.
                                          ds.DataContextChanged += ds_DataContextChanged;
                                          Будет тоже самое, если типы друг с другом «дружат»
                                  • +5
                                    LINQ же
                                  • +3
                                    Меня удивило, что в примере (понятно, что helloWord классика) не применяется C# вообще, нужно было его изменить немного, чтоб показать применение именно C#. Например использовать StringBuilder для по буквенного создания строки «Hello word». А так получается непонятно совершенно в чём прикол.
                                    • 0
                                      Берем проект AnimatedHelloWorld, открываем MainActivity.cs, меняем код метода OnCreate на следующий:
                                              protected override void OnCreate(Bundle savedInstance)
                                              {
                                                  base.OnCreate(savedInstance);
                                                  SetContentView(R.Layouts.MainLayout);
                                                  var text = (TextView) FindViewById(R.Ids.theLabel);
                                      
                                                  StringBuilder sb = new StringBuilder();
                                      
                                                  text.Text =
                                                      sb.Append("H")
                                                        .Append("e")
                                                        .Append("l")
                                                        .Append("l")
                                                        .Append("o")
                                                        .Append(",")
                                                        .Append(" ")
                                                        .Append("H")
                                                        .Append("a")
                                                        .Append("b")
                                                        .Append("r")
                                                        .ToString();
                                      
                                                  var animation = AnimationUtils.LoadAnimation(this, R.Anims.Animation);
                                                  text.SetAnimation(animation);
                                                  animation.Start();
                                              }
                                      

                                      Наслаждаемся анимированным результатом!
                                      • +1
                                        А что, в Java нет класса StringBuilder?
                                        • +2
                                          есть
                                          • +3
                                            Так как же в таком случае StringBuilder раскрывает «применение именно C#»?
                                            • +2
                                              ни в каком)
                                              • 0
                                                Отличный коммент!
                                            • 0
                                              Не зал, что в java есть StringBuilder, но всё равно нужно оперировать обоими языками — AnimationUtils.LoadAnimation и FindViewById… или это переписанные ребятами классы и функции на C#? Точно такие же есть на java при программировании под android это я точно знаю.
                                              • +1
                                                «Оперировать обоими языками» — неверный термин. Язык один — C#, а вот доступных библиотек — две (стандартная C# и AndroidSDK)
                                      • +2
                                        Есть желающие собрать terraria?)
                                        • +4
                                          Это круто! Простая установка, раз два и заработало!
                                          Наконец-то я, закоренелый сишарпер, смогу под свой ведроид что-то писать. А то с другими тулзами никак не срасталось, муторно, энтузиазм угасал раньше, чем получалось хоть что-то запустить.
                                          • +1
                                            Все это, конечно круто, но печалит тот факт, что все это стоит вполне себе некисло, что dot42, что xamarin и, соответственно, все закрыто… В отличие от того же Qt… :(
                                            • +1
                                              Qt тоже имеет коммерческую лицензию и если для пк можно использовать LGPL, то когда он обзаведется поддержкой мобильников, то скорее всего придется купить лицензию.

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