Кросс-языковая разработка ПО

Задача


Вот бы, разрабатывая программу на одном языке, сразу получать исходники на других языках программирования… Я пишу на C# .NET, но в последнее время всё больше требуется интегрироваться с Java. Одно из решений — оформление web-сервисов для взаимодействия, но не то это, не то. Вроде и существуют конвертеры C# в Java, но эксперимент показал, что для реального проекта они (те, что удалось попробовать) не работают, хотя на «hello world» отрабатывают отлично. Переписать с нуля на Java весь проект нереально — он активно разрабатывается более 6 лет (Pullenti — обработка естественного языка), да и на C# он нужен. Пришлось мобилизоваться и в прошлом году написать этот конвертер, а в этом году и конвертер C# в Python.

Опыт создания конвертера C# в Java


Итак, на входе проекты (solution) Visual Studio, нужно получить классы на Java. Разумеется, не все типы проектов возможно поддержать, но тип «Class Library» и «Console Application» — вполне. Проекты не должны использовать никакие графические библиотеки типа System.Drawing, никакие Windows-возможности или DllImport, а для используемых библиотек должны существовать аналоги в Java. К счастью, для используемых мной возможностей такие аналоги нашлись (работа с XML, архивы GZip и др.). От некоторых несущественных деталей пришлось отказаться, немного подправив алгоритмы. На уровне языка C# и Java близки, но Java чуть беднее — вот что в нём отсутствует:

  • property { get; set; } — приходится работать с функциями;
  • struct — структуры отсутствуют, поэтому сначала я их моделировал просто классами Java, но затем переписал алгоритм, отказавшись от них полностью;
  • delegate — отсутствуют, но моделируются интерфейсом с одной функцией;
  • event — моделируется массивом ArrayList из элементов класса, реализующего интерфейс соответствующего delegate;
  • out и ref аргументы у методов — моделируется классами с одним полем Value;
  • internal — этот модификатор вообще не имеет смысла в Java, так как отсутствует понятие сборки, поэтому просто заменяется на public;
  • new Class() { присваивания } — приходится создавать статическую функцию, в которую выносить эти присваивания;
  • enum — если в C# возможны побитовые операции с его элементами, то в Java это запрещено, и конвертеру приходится enum преобразовывать в классы Java;

Но не это оказалось самое сложное — проблема с огромным количеством системных функций, для которых нужно было искать аналоги. Для некоторых аналогов не нашлось, и пришлось писать их на Java, создавая свою библиотечку, которая добавляется при генерации к результирующим исходникам Java. Например, в C# для потоковых операций ввода-вывода есть базовый класс Stream, а в Java два отдельных класса InputStream и OutputStream, и поэтому нужна некоторая «обёртка» над ними.

Если нужно было исключить из кода C# некоторый фрагмент или оформить его немного по-другому для Java, то использовались директивы препроцессора #if JAVA… #else… #endif.
Вот так, постепенно дополняя конвертер новыми функциями и подправляя исходный код на C#, удалось прийти к тому, что генерируемые на Java более чем 1500 юнит-тестов стали отрабатывать правильно, как и их прототипы на C#.

Сравнение скорости работы .NET и Java


Теперь самое интересное. Есть трудоёмкий алгоритм (в основном работа со строками), и абсолютно идентичные его реализации на C# и Java. Как «апологет» .NET, я всегда сомневался в эффективности Java. Но оказался неправ — C# всего на 15-20% быстрее Java (запускал из Eclipse под Windows), а не в несколько раз, как ожидалось. А какова ситуация с Python? Читайте дальше.

Опыт создания конвертера C# в Python


В Python оказалось конвертироваться даже проще, чем в Java. Основа была готова, осталось только подправить генератор на новый язык и найти (написать) аналоги используемых функций.

Что в Python отсутствует или неудобно:

  • for(init, cond, incr) — в полноценном виде отсутствует, есть некоторые частные случаи с range, но в основном приходится моделировать через while;
  • switch — отсутствует, моделируется if-then-else-ами;
  • interface — отсутствует, но это просто класс с пустыми методами;

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

Сравнение скорости работы .NET и Python


Многие жалуются на низкую скорость работы Python, но насколько она низка? И низка ли? Пришло время сравнить на том же алгоритме, что и для Java (точнее, на тех же юнит-тестах). Готовы? Итак, Python работает в 30 раз медленнее, чем .NET (запускал в Eclipse под PyDev).

Причина, думаю, в следующем. В Python отсутствуют простые типы как ValueType (насколько я понял), и даже обычные числа — это полноценные объекты (фактически как boxing в .NET). И элемент строки — это не символ, а тоже строка из одного символа! То есть string[i] — это не char, а как бы string.Substring(i, 1) в .NET.

Технология кросс-языковой разработки


На основе личного опыта скажу, что возможно разрабатывать на одном языке и платформе и автоматически переносить на другие языки и платформы. Свой базовый проект разрабатываю на .NET Framework 4.0, и в любой момент имею функционально эквивалентные:

  • исходники на Java (конвертер);
  • исходники на Python (конвертер);
  • проекты на .NET Core (отдельные csproj-файлы, но исходники те же);
  • проекты на .NET Framework 2.0 (конвертер, и такое нужно для одного заказчика);

Поделюсь одной полезнейшей возможностью Visual Studio, которой почему-то мало пользуются даже профессиональные разработчики C#, к моему глубокому удивлению. И которая отсутствует в средствах разработки, скажем, для Java. А именно — возможность изменять код и перемещать текущую позицию прямо в ходе выполнения, причём состояние всех переменных сохраняется и можно продолжить выполнение с учётом внесённых изменений. Это кардинальным образом облегчает отладку, особенно когда для воспроизведения нужной ситуации требуется некоторое время. Например, я включаю режим, при котором Visual Studio приостанавливает программу в месте возникновения Exception (вернее, я этот режим никогда не отключаю), запускаю длительную обработку, а через сколько-то минут или часов возникает эта ситуация, чаще всего NullReference. Я исправляю код, и вместо того, чтобы перезапускать программу, перемещаю точку выполнения на нужный оператор назад и запускаю выполнение дальше. Да и вообще частенько я прямо в ходе выполнения реализую сложные алгоритмы в нужных местах. Помнится, когда делал систему биржевой торговли, то это на порядок облегчало жизнь в условиях трудоёмкой процедуры инициализации и выхода на нужную алгоритмическую ветвь. В Visual Studio эта возможность достигается за счёт тесной интеграции IDE и компилятора — они могут себе такое позволить. Но вернёмся к технологии.

Ограничения очевидны — только библиотеки и консольные приложения. Почти нереальны конечные приложения с пользовательским GUI или Web-приложения. Да и при разработке библиотек приходится придерживаться ограничений, накладываемых требованием универсальности. От чего-то придётся отказаться, что-то переписать, но результат стоит затраченных усилий!
Поделиться публикацией
Комментарии 81
    0
    Хорошая статья, спасибо.
    А по поводу изменения кода в памяти и перемещения указателя: можно просто поставить брейкпоинт и в нём уже запустить Evaluation окно с отдельным кодом внутри, который подцепит все переменные и так далее.
    • НЛО прилетело и опубликовало эту надпись здесь
        +1
        Ничего удивительного, если судить по доменной зоне и рассказам о том, что там были структуры и всякая другая магия, можно предположить, что там много сложной математики и алгоритмики именно с числами и прочим.

        А тут нужны cython + numpy и сверху еще numba было бы неплохо. А чистый python сильно проигрывает :(

        Ну или pypy, как предлагают ниже, но numba должна быть круче.
          +1
          основные реализации python — не полноценные вм, как у java/c#, а обычные не оптимизирующие интерпретаторы. python хорош для использования библиотек (особенно написанных на c/c++), но не для их написания. И уж тем более не для арифметических задач.
            +1
            www.researchgate.net/figure/Speed-comparison-of-the-Neighbor-Joining-program-Speed-comparison-of-the_fig2_5600272

            Вы даже не представляете, как ошибаетесь.
            Python везде выдаёт самый худший результат по производительности.
              0
              Да что на него смотреть — код как код. А вот сгенерированные коды на Java и Python можно посмотреть на сайте (www.pullenti.ru/DownloadPage.aspx). А первая задача была — это чтобы сам генератор, который на .NET, перевёл сам себя в Java и также работал.
              0

              Попробуйте использовать PyPy вместо CPython, он с JIT компиляцией. На данный момент поддерживает Python до 3.5 включительно. (Легко) можно получить прирост в скорости до x10. Код переписывать не надо.

                0
                Извиняюсь, забыл указать в статье, что Python запускал в Eclipse под PyDev (подправил статью). Может, в какой другой среде это будет побыстрее.
                +11
                а не логичнее ли наладить interoperability компонентов, написанных на разных языках?
                Но оказался неправ — C# всего на 15-20% быстрее Java (запускал из Eclipse под Windows), а не в несколько раз, как ожидалось

                вы всерьез сравниваете производительность оригинального C# кода и автогенерированного, использующего оболочки и эмулирующего C#-концепции Java-кода?
                  –8
                  Не проще просто писать на java, которая в отличие от кое-чего запускается на нормальной серверной ОС? Виндовс-сервер это оксюморон. В тепличных условиях пусть будет +15% (лениво проверять), а через полгода шындовш уже пучит и таращит, через год минус 50% производительности
                    +11
                    Стыдно в 2018 поливать грязью .net-платформу и не знать про .net core
                      –6
                      Стыдно должно быть сравнивать зрелые платформы SE и EE с этим. Когда от например RedHat появится решение и саппорт, тогда и поговорим о core
                        +5
                        Как определяется зрелость платформ? Год, пять или десять лет?

                        На RHEL есть поддержка .net core: пруф.
                          –6
                          Если мерять годами, то язык brainfuck (создан в начале 90х) всегда будет более зрелым решением, чем net core. Шах и мат, микрософт. :) не вижу смысла продолжать тему сравнения зрелости net и java
                        +7

                        perfectdaemon mspain
                        Попробую примирить. mspain — вы неправы в 2018 году, dotnet core очень годится для продакшена на RedHat. Сам пишу на нем и на Scala. Кроме того, в 2018 году Java — убогий язык и писать на нем изначально, плохая мысль.
                        perfectdaemon с товарищем надо полегче. Дело в том, что некомпетентный майкрософт много лет игнорировал линукс, заявлял что open source — это рак, при этом не имея вообще ничего на сервере. Хуже того, армия майкрософтовских фанбоев поддерживала всю эту галимотью. Тот факт, что теперь у мс и его сообщества есть хейтеры — это нормальная реакция. Теперь надо делать добро и адекватные шаги ровно столько же времени, сколько они подсиради опен сорсу вообще и линуксу в частности, т.е. Ещё лет 10. Репутация — такая штука…

                          –3
                          По вашему если что-то сделать опенсорсным, оно мгновенно и обязательно превращается в конфету? У МС есть что-то подобное java EE? Если нет, то им еще лет 10 надо сидеть молча и пилить, пилить.
                            +2
                            Есть. И подобное и бесподобное.
                              0
                              asp.net чтоли? фанбои, такие фанбои
                                +1
                                Тут вы тоже проспали, возможно.
                                ASP.Net Core 2.0 — это сильно отдельный продукт от старого убогого ASP.Net. Вот тут я его ругал. Но если отвлечься от неразберихи, которые создал майкрософт вокруг ASP, то само поделие норм — на уровне современных веб-фреймворков на других технологиях.

                                Если что, я не фанбой, мои последние 5 лет: 3 года Java, 1 год F#, 1 год Scala.
                              +1
                              Нет, по-моему вне зависимости от результата, компания которая поддерживает опенсорс делает добро и себе и миру. Поддерживает не только тем, что опенсорсит свой код, но и использует и улучшает существующие опенсорсные продукты вместо того, чтобы пилить свои закрытые альтернативы, но хуже. Майкрософт на этом пути уже последние 2-3 года.

                              Мне кажется, вы зашкварились в вашем хейтерстве. Не любить и желать исправиться — это норм. Не любить, игнорировать факты и желать смерти — это затягивает вас на темную сторону силы и вы больше не можете видеть того (может быть и немного) хорошего, что происходит.

                              Вот вы начали про нормальную ОС, а люди вам говорят, что есть нормальная ОС в дотнете. Вы не правы.
                              Вот вы сказали про отсутствующую поддержку от RedHat. Так вам говорят, что есть поддержка. Вы не правы.
                              Понимаете, если вы были не правы 2 раза, то уже надо думать, что что-то не так в ваших размышлениях или знаниях. Если такой мысли у вас не появляется, то вы такой же как идиотские фанбои. Никто не хочет быть как они…

                              Теперь про Java и Java EE. Вы уверены, что вы хорошо видите ландшафт мира Java? Вы не заметили, что Java как язык полный отстой в 2018. Даже разработчики Java это заметили и начали добавлять в язык те фичи, которые от них просили еще 10-15 лет назад. Компании переходят (или уже перешли, как Amazon, например) на Scala, Kotlin массово. А в это время C# хоть и был одноплатформенным (оооочень большой минус), но как язык был очень норм. Конечно, есть люди, которые считают, что в Java все было и есть классно, но это к психиатру.

                              Так вот, Java прежде всего — это не EE, это мегастабильная JVM и куча библиотек на любой вкус. Поэтому и развиваются другие языки и поэтому они популярны — не надо создавать всю инфраструктуру с нуля — только компилятор. [Хвала опенсорсному подходу, при котором все получается модульным] Многие новые библиотеки и фреймворки игнорируют Java EE. А «новые» подходы типа микросервисов и облачного контейнерного развертывания делают почти все продукты из мира Java EE бессмысленными.

                              Вобщем, я не агитирую за дотнет. Пожалуйста, посмотрите повнимательнее на ту платформу, на которой вы работаете.
                                –3
                                Самый кривой софтописатель планеты выпустил Net core 2 восемь месяцев назад, и оно уже успело порвать по всем фронтам java ee с 20 летней историей и десятками независимых вендоров. Ещё и такие откровения, что java в 2018 году вдруг испортилась. Прямо как селёдка, два года назад вполне ничего было, но внезапно всё пропало. Еще про раст расскажите, как он убил java и cи.
                                  +1

                                  Ой, ну всё!

                                    0

                                    Ну судя по бенчмаркам неплохо рвет. Единственно что в регулярках в аутсайдерах.

                                –1
                                У меня, кстати, к МС претензии ко всем продуктам от кривого гипервизора до отвратительного Word-а (жизнь заставляет иногда в нем верстать). Так что опенсорсность core ничего не меняет
                                  0

                                  Это ведь статья про кросс-языкоаую разработку?
                                  Это хорошо, что у вас есть претензии — их надо высказывать. Но как бы контекст никто не отменял. В области кроссплатформенной разработки мс ведёт себя хорошо и стоит на пути искупление своих былых грехов.


                                  А Word разве не умер? Как и конкурирующие с ним Libre Open'ы? Офисный планктон вышел в облака и использует Google Drive, не?

                                    0
                                    Офисный планктон вышел в облака и использует Google Drive, не?

                                    Не, офисный энтерпрайзный планктон плотно сидит на Office365, где ворд и вообще весь офис, тимс, скайп давно в браузере.

                                      0
                                      Со всем уважением, я знаю очень мало девелоперских контор которые именно на таком стеке. В основном: Google Drive, Hangouts/HipChat/Slack, Confluence (обычно вместе с Jira)…
                            –1
                            Ещё очевидно, что программы не берут данные из воздуха и не складывают в воздух. А известно как в винде работают субд. Какая тормозная ntfs и тд и тп. В итоге скорость ПРОГРАММНОГО КОМПЛЕКСА под net обгоняет java только при очень непрямых руках и в get the facts
                              +1
                              винде работают субд

                              Причем тут винда и субд. Например, сейчас есть в продакшене система на .netFramework, которая ходит на Oracle, который в свою очередь установлен на линуксе.
                              Плюс майкрософт сделала порт своего SQL Server на линукс. поэтому ограничений в .net, почти нет (ну кроме нормальных кроcплатформенных ГУИ, но я бы тут взял или QT или Electron)
                                –1
                                Клиент на dotnet, бизнес-логика на могучем plsqlчике, третий уровень не завезли? Я тоже видел тонны подобного крапа от подрядчиков нашей конторы. К обсуждаемой теме performance оно каким боком? :)
                                  0

                                  Погодите, а вы что север на Java запускаете всегда на той же машине, что и сервер баз данных?

                              0
                              вы всерьез сравниваете производительность оригинального C# кода и автогенерированного, использующего оболочки и эмулирующего C#-концепции Java-кода

                              Ну да, тем более, что обёрток там не так уж много, и для несущественных для производительности объектов. А так всё идентично — классы, методы, циклы, ветвления, массивы и пр. стандартные конструкции. Хотя, может, каких-либо «блох» и можно отловить. В принципе, генерируемый код Java выложен на pullenti.ru/DownloadPage.aspx, если Вы там обнаружите навскидку какие неэффективности — буду признателен!
                              0
                              Еше во времена .NET 1.0 сами Microsoft такое пробовали (конвертер из Java в C#, ЕМНИП было в VS.NET 2003). Не взлетело, и уже в VS 2005 убрали. А наоборот — полагаю что даже сложнее будет.
                                0

                                Наверное имеется в виду J#
                                https://ru.m.wikipedia.org/wiki/Visual_J_Sharp


                                "Заявленной целью разработки Visual J# было облегчение перехода разработчиков с платформы Java на платформу .NET Framework. Однако эта цель достигнута не была" =)

                                0
                                Редактирование кода на лету имеет ряд ограничений: нельзя добавлять/удалять классы/внутренности классов, нельзя править генераторы и прочие методы, которые разворачиваются в машины состояний, нельзя править методы, содержащие лямбды, и многое другое. Остаётся процентов 20-30 тривиальных случаев.
                                  0
                                  Зависит от проекта. У меня таких случаев как раз 80-90% (обработка естественного языка), и весьма нетривиальных.
                                  +3
                                  Код на производительность тестировался как? Сконвертированный сравнивался с исходником, или нормально переписывался с учётом особенностей целевого языка? В первом случае любой код будет медленнее исходного языка.
                                    0
                                    Нормально переписать нет никакой возможности — проекту около 7 лет, там сложные алгоритмы лингвистической обработки, морфологический анализ, выделение именованных сущностей (NER). Повторю, что использовались только «стандартные» языковые конструкции, эквивалентные в .NET и Java (от экзотики я избавился в ходе работы над конвертером). Не думаю, что можно как-то существенно оптимизировать код Java (см. результат генерации pullenti.ru/DownloadPage.aspx?file=PullentiJava.zip). Может, есть какие тонкие настройки оптимизации в самой среде Eclipse. Например, когда я начинал запускать в NetBeans, то там скорость почему-то была медленнее раза в 2. Скажем, в Visual Studio в режиме Debug скорость меньше на такие же 15-20%, чем в Release. Хорошо бы ещё проверить под Unix, но нет под рукой. Но в целом можно утверждать, что скорость примерно одинакова.
                                      0
                                      То есть в сущности это не сравнение производительности, а просто проверка того, насколько просела производительность после автоматической миграции.
                                    0

                                    Так как есть JPython, то может быть даже достаточно перегонять только в питон, для джавы написать отдельно интерфейс.

                                      +1
                                      В Java тоже есть редактирование кода на лету, правда работает оно не из коробки — нужно запускать на пропатченном jvm и с java agent'ом. (Для dcevm актуально). Это всё не сложно сделать. Хотя перенос, как вы выразились, «текущей позиции», всё же не поддерживается, насколько я знаю.
                                      dcevm.github.io бесплатная
                                      zeroturnaround.com/software/jrebel платная, очень платная
                                      Я пользовался обеими и для большинства случаев первого хватит. Насколько я помню, основное отличие в поддерживаемых framework'ах — т.к. при изменении кода иногда нужно учитывать работающие в приложении framework'и и дёрнуть их методы (например, добавили поле которое испольуется в DI и его нужно инициализировать, вот dcevm и jrebel посмотрять, что у вас за DI framework используется и применят его)
                                      Но по опыту — если такая фигня начинает быть важна, значит что то не то в архитектуре приложения — поидее всю логику работы нужно уметь востанавливать по логам и быстро воспроизводить в тестах. По крайне мере мне эти штуки пригодились только на таких проектах — тестов нет, запускается очень долго, и поэтому приходиться в run time код писать :-)
                                      P.S. давно статью по dcevm писал, может пригодиться, habr.com/post/236075
                                        –1
                                        В Python отсутствуют простые типы как ValueType (насколько я понял), и даже обычные числа — это полноценные объекты (фактически как boxing в .NET).
                                        Это ерунда. В дотнете значимые и примитивные типы — это не одно и то же. Например, string — примитивный, но ссылочный, а Decimal — значимый, но не примитивный.

                                        Каким образом вы определяли, что обычные числа используются как объекты? Вы смотрели ассемблерный код, генерируемый JIT? Я не знаток питона, но практически уверен, что проблема производительности не в нем, а в том, что ваш генератор выдает неэффективный код.
                                          +1
                                          Например, string — примитивный

                                          Да, ладно!
                                          var isPrimitive = "Hello World!".GetType().IsPrimitive;
                                          Console.WriteLine(isPrimitive);
                                          >>out -> false
                                          
                                            0
                                            С точки зрения CLR тип string вполне себе примитивный: для него есть отдельный опкод, его можно использовать в аргументах атрибутов и в константах. А свойство просто проверяет текущий тип на вхождение в некий список. Если пытаться сформулировать правило, по которому здесь определяется примитивность типа, то оно получается длинным и неуклюжим. Поэтому я подозреваю, что на самом деле причина историческая: так реализовали в первой версии, а потом не стали менять для сохранения обратной совместимости.
                                              0
                                              Если пытаться сформулировать правило, по которому здесь определяется примитивность типа, то оно получается длинным и неуклюжим

                                              Зачем формулировать правило, которого нет в спецификации языка C#?
                                              Даже Джон Скит, не называет string примитивным типом и полностью доверяет type.Isprimitive

                                              I wouldn't personally call dynamic, decimal, object or string primitive types. I'd use Type.IsPrimitive for the canonical source there.


                                              Источник
                                              stackoverflow.com/a/47589777
                                                0
                                                Во-первых, в спецификации языка C# определения примитивности и не может быть, потому что это более низкоуровневая вещь, относящаяся ко всему CLR.

                                                Во-вторых, именно отсутствие нормального определения побуждает к попытке сформулировать свое. В ECMA-335 я такого не нашел, всё так или иначе упирается в это самое свойство IsPrimitive, а рекурсивное определение, даже подтвержденное личным мнением Джона Скита, на мой взгляд бесполезно.

                                                Для себя я определяю «примитивный» тип как нечто базовое, что CLR особым образом использует и на что полагается. Под такое определение строка подходит — в формате метаданных CLI есть даже отдельная секция для хранения строк.

                                                Какое определение больше нравится — решать вам. Но если вы знаете ситуацию, в котором текущая реализация IsPrimitive имела бы осмысленную практическую пользу — пожалуйста, поделитесь.
                                                  0
                                                  в спецификации языка C# определения примитивности и не может быть

                                                  Ага, а вот в спецификации VB.NET есть секция 7.3
                                                  The primitive types are identified through keywords, which are aliases for predefined types in the System namespace.

                                                  Там же, кстати, к примитивным типам относят и Decimal, Date

                                                  Для себя я определяю «примитивный» тип как нечто базовое,

                                                  Так и писали бы в первоначальном сообщении ИМХО — вопросов бы не было.

                                          +3
                                          Вот бы, разрабатывая программу на одном языке, сразу получать исходники на других языках программирования

                                          Haxe (https://haxe.org/), не?
                                            0
                                            Да, наверное, неточно выразился. Правильнее было бы так:
                                            Вот бы, разрабатывая программу на одном моём любимом языке C#, сразу получать исходники на других распространённых языках программирования Java и Python
                                            0
                                            DEL
                                              +1

                                              Был же вроде проект наоборот, конвертировали Андроид с Явы на Сишарп.

                                                0
                                                А что будет с NuGet-пакетами?
                                                  0
                                                  Если нет аналога в Java — то никак не конвертируется. Или использовать исходники пакета, если есть, для конвертации и их в Java. Увы, есть ограничения… Например, связанные с использованием GUI или некоторых Windows-возможностей (какой-нибудь реестр). Но в рамках, скажем, функционала .NET Core этих ограничений будет меньше.
                                                  0
                                                  Для таких задач можно попробовать GraalVM.

                                                  C# нет, но есть Truffle и возможность имплементить свой язык.
                                                    0
                                                    А как именно вы делали конвертацию? Этого в статье не хватает.
                                                      0
                                                      Сначала попробовал конвертеры C# в Java из Интернета (парочку), но они выдавали некомпилируемый результат с кучей ошибок. Может, есть какие платные получше, но денег разбираться нет. Писал сам, на это ушло около 3-х месяцев, зато теперь конвертирует то, что нужно, и как нужно сразу рабочий код. Задача была добиться того, чтобы результат вообще не нужно было бы вручную как-либо корректировать. Поскольку такие генерации идут периодически при доработках исходного проекта на C#. А в этом году за месяц доделал конвертер для получения Python. Но это так — экзотика, так как реальных проектов у меня для Python нет.
                                                      +3
                                                      Может быть язык Haxe — это то, что вам нужно
                                                        0
                                                        Да, наверное, неточно выразился в начале статьи. Правильнее было бы так:
                                                        Вот бы, разрабатывая программу на одном моём любимом языке C#, сразу получать исходники на других распространённых языках программирования Java и Python
                                                        0

                                                        Месье знает толк в извращениях...


                                                        Если верно понял, Пайтон был по фану
                                                        А не хотите во что-нибудь поэкзотичнее конвертнуть?
                                                        Например Go или Rust))

                                                          0
                                                          «Штирлиц был извращенец, поэтому во Вращенцах ему был установлен памятник.» Могу и в Go, если там будет не памятник, а хотя бы небольшой бюстик…
                                                          0
                                                          «new Class() { присваивания }»

                                                          в Java — new Class() {{ присваивания }}
                                                            0
                                                            Надо же, не знал! Спасибо, оказывается, так можно — подправлю конвертер.
                                                              0
                                                              Это не то же самое. Этот вариант создаёт анонимный класс.
                                                              Не стоит править — просядет производительность.
                                                                0
                                                                Так делать нельзя. Это уже будет не `Class`, а некий другой, анонимный `Class`.
                                                                // Я буду обновлять комментарии перед отправкой своего.
                                                                  0
                                                                  Что тут анонимного, это блок инициализации?
                                                                    0

                                                                    Всё верно, блок инициализации в неком классе-наследнике Class,


                                                                    (new Class().getClass() != new Class() {{}}.getClass()) == true

                                                                    Это корректная конструкция, но делать так не рекомендуется.(пока не понимаешь, что творишь и почему этот код может сломать буквально всё)

                                                                      0
                                                                      Интересно, почитать об этом где-нибудь можно
                                                              +1
                                                              Похвально. Но, есть такая штука как IKVM.NET. Разработка относительно недавно прекратилась, однако, позволяет запускать почти любой JVM байткод на .NET, и при том умеет не только интерпретировать, но и компилировать. Так, кстати говоря, можно из Java в C# перегонять код, при помощи декомпилятора. И даже Interop с Java есть, можно создать jar-обертку для.NET кода и использовать ее при разработке на Java, с одним ограничением — код должен исполняться в IKVM.
                                                                0

                                                                Лучше конечно конвертировать на уровне байт кода, а не исходного кода. Я встречал на хабре несколько таких проектов, например CIL2Java, был еще dot42 и множество других.

                                                                  0
                                                                  Чем лучше?
                                                                    0
                                                                    Тем что можно конвертировать «бинари», например, из nuget…
                                                                  0

                                                                  Интересно, мы в Swiftify занимаемся конвертером Objective-C в Swift, и я могу сказать что это непростая задача.


                                                                  А какие вы использовали библиотеки для парсинга и обработки C#, Java и Python?

                                                                    0
                                                                    Да, весьма непростая задача. Никакие библиотеки не использовал (попробовал Roslyn, но сразу не взлетело, да и лень было разбираться) — писал свой парсер C# с нуля. А для java и Python парсер был не нужен. Отмечу, что сам по себе парсер в общих трудозатратах занял не так уж много времени — 10-15%, не более.
                                                                      0
                                                                      попробовал Roslyn, но сразу не взлетело, да и лень было разбираться

                                                                      Извините, но написать свой парсер с нуля намного сложнее чем разобраться в Roslyn. Тем более он предоставляет не только парсер, а еще и семантический анализатор. Как проверяли корректность парсера? Ведь в C# есть препроцессорные директивы.

                                                                        0
                                                                        Кому как, мне приятнее написать самому, чем разбираться. Препроцессорные директивы активно используются — в конвертере можно задавать переменные и потом их проверять в коде, отключая те или иные ветки через препроцессорные директивы. А корректность доказывается тем (как необходимое условие), что результирующий Java\Python функционирует идентично исходному C#.
                                                                          0
                                                                          Как понимаю, исходники закрытые, это коммерческая разработка? :)
                                                                            +1
                                                                            Да, жалко так вот бесплатно… К тому же что там такого интересного — в исходниках? Мне сейчас видится, что 100% конвертера сделать в общем случае затруднительно, но на конкретные проекты — вполне. Скажем, я использую только некоторое подмножество .NET (вряд ли больше 70% языка и 10% функций). Если у кого есть схожая задача конвертации, то мог бы взяться за поддержку конвертации этих проектов, небескорыстно, естественно. Судя по сайту, Вы тоже занимаетесь конвертацией. Можем обменяться идеями по скайпу (konstantin.smith), покажу через TeamViewer, как это выглядит у меня.
                                                                    0
                                                                    По поводу Java<->.NET есть такой «диназавр» IKVM.NET. Умеет бинарники в jar и наоборот. Но я так понял вам важно иметь именно исходники.
                                                                      0
                                                                      По поводу internal… У меня в голове прочно сидит такая аналогия:
                                                                      C# -> сборка — Java -> пакет
                                                                      internal — package private
                                                                        0
                                                                        Не совсем. Прямого аналога сборки в Java нет, я делал C# namespace — Java-пакет, а internal приходилось делать public.
                                                                        0

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

                                                                        Самое читаемое