Task
That would be, developing a program in one language, immediately get the source code in other programming languages ... I am writing in C # .NET, but lately more and more need to integrate with Java. One of the solutions is to design web services for interaction, but not this, not that. It seems there are C # converters in Java, but the experiment showed that for a real project they (those that managed to try) do not work, although they work on the “hello world” perfectly. Rewriting the entire project from scratch to Java is unrealistic - it has been actively developed for more than 6 years (Pullenti is a processing of natural language), and in C # it is needed. I had to mobilize last year to write this converter, and this year, and the converter C # to Python.
Experience creating a C # converter in Java
So, at the input of the projects (solution) of Visual Studio, you need to get classes in Java. Of course, not all types of projects can be supported, but the type “Class Library” and “Console Application” is completely. Projects should not use any graphical libraries such as System.Drawing, no Windows features or DllImport, and for libraries used, there must be analogues in Java. Fortunately, for the features I used, such analogs were found (work with XML, GZip archives, etc.). Some minor details had to be abandoned, slightly tweaking the algorithms. At the level of C # and Java are close, but Java is slightly poorer - that's what is missing in it:
- property {get; set; } - you have to work with functions;
- There are no struct structures, so at first I modeled them simply by Java classes, but then I rewrote the algorithm, abandoning them completely;
- delegate - no, but modeled interface with a single function;
- event - modeled by an ArrayList array of class members that implement the interface of the corresponding delegate;
- The out and ref arguments of methods are modeled by classes with one field Value;
- internal - this modifier does not make sense at all in Java, since the concept of an assembly is missing, therefore it is simply replaced by public;
- new Class () {assignments} - you have to create a static function into which to make these assignments;
- enum - if in C # bitwise operations with its elements are possible, then in Java this is prohibited, and the converter has to convert enum to Java classes;
But it was not the most difficult thing - the problem with a huge number of system functions, for which it was necessary to look for analogues. For some, there were no analogues, and I had to write them in Java, creating my own library, which is added when generating to the resulting Java sources. For example, in C #, for streaming I / O is the base class Stream, and in Java there are two separate classes, the InputStream and OutputStream, and therefore some “wrapper” over them is needed.
If it was necessary to exclude some fragment from the C # code or arrange it a little differently for Java, then the preprocessor directives #if JAVA ... # else ... #endif were used.
So, gradually adding new functions to the source code and correcting the source code in C #, we managed to come to the conclusion that more than 1,500 units of tests generated by Java began to work properly, like their C # prototypes.
')
Comparison of the speed of .NET and Java
Now the fun part. There is a time consuming algorithm (basically working with strings), and absolutely identical implementations of it in C # and Java. As an .NET apologist, I have always doubted the effectiveness of Java. But it turned out to be wrong - C # is only 15-20% faster than Java (launched from Eclipse under Windows), and not several times as expected. What is the situation with Python? Read on.
Experience creating a C # converter in Python
In Python it turned out to be converted even easier than in Java. The basis was ready, it remains only to correct the generator to a new language and find (write) analogs of the functions used.
What is missing or uncomfortable in Python:
- for (init, cond, incr) - is absent in its full form, there are some special cases with the range, but mostly you have to model through while;
- switch - absent, modeled if-then-else;
- interface is absent, but it is just a class with empty methods;
A very inconvenient system for importing other classes, leading in some cases to cyclical dependence and the impossibility of importing at all. I had to keep track of these dependencies and make some imports at the method level, not the entire file with the class. Despite these and other difficulties, we managed to achieve the correct execution of those 1500 unit tests.
Comparing the speed of .NET and Python
Many complain about the slow speed of Python, but how low is it? And is it low? It's time to compare on the same algorithm as for Java (more precisely, on the same unit tests). Ready? So, Python is 30 times slower than .NET (launched in Eclipse under PyDev).
The reason, I think, is as follows. In Python, there are no simple types like ValueType (as I understand it), and even ordinary numbers are fully-fledged objects (actually like boxing in .NET). And the string element is not a symbol, but also a string of one character! That is, string [i] is not a char, but, as it were, a string.Substring (i, 1) in .NET.
Cross-language technology
On the basis of personal experience, I will say that it is possible to develop in one language and platform and automatically transfer to other languages and platforms. I develop my base project on the .NET Framework 4.0, and at any moment I have functionally equivalent:
- Java sources (converter);
- Python sources (converter);
- projects on .NET Core (separate csproj-files, but the sources are the same);
- projects on the .NET Framework 2.0 (converter, and this is needed for one customer);
I will share one very useful feature of Visual Studio, which for some reason is not widely used even by professional C # developers, to my deep surprise. And which is missing from development tools, say, for Java. Namely, the ability to change the code and move the current position directly during execution, and the state of all variables is preserved and you can continue execution with the changes made. This dramatically simplifies debugging, especially when it takes some time to reproduce the desired situation. For example, I turn on the mode in which Visual Studio pauses the program at the Exception site (or rather, I never turn off this mode), start a long processing, and after a few minutes or hours this situation occurs, most often NullReference. I correct the code, and instead of restarting the program, I move the execution point to the desired operator back and run the execution further. In general, I often implement complex algorithms in the right places right during the execution. I remember when I did the system of exchange trading, it made life much easier in the conditions of the time-consuming procedure of initialization and access to the necessary algorithmic branch. In Visual Studio, this feature is achieved through tight integration of the IDE and the compiler - they can afford it. But back to technology.
The limitations are obvious - only libraries and console applications. Finite applications with a custom GUI or Web application are almost unreal. And when developing libraries, one has to adhere to the limitations imposed by the requirement of universality. You have to give up something, rewrite something, but the result is worth the effort!