So earlier today I found about IronPython:

IronPython is an open-source implementation of the Python programming language which is tightly integrated with the .NET Framework.

This was my first experience with using multiple programming languages in a single program. I thought it was really cool that I could effectively call my python script as a wrapper for the dll compiled from C#.

But this got me thinking.... how many more programming language could be attached to this - is there limit? What are some other programming languages that have a similar feature?

  • 1
    Since nearly all programs are Turing complete - nearly all of them. In practice too, though many practically need to go through some C library to do it nicely. – Telastyn Jul 12 '19 at 2:39

how many more programming language could be attached to this - is there limit?

There is no limit. You can use as many programming languages in a single program as you want.

Using more than one language in the same project (but not necessarily the same program) at the same time is called Polyglot Programming.

There is even a programming paradigm called Language-Oriented Programming, where you not only use more than one language within the same program at the same time, but you actually create languages to fit your problem domain. Just like you create many many different highly specialized objects to solve a specific sub-problem in Object-Oriented Programming, you create many many different highly specialized programming languages to solve a specific sub-problem in LOP.

What are some other programming languages that have a similar feature?

It's not a feature of the programming language, as you have discovered yourself, it is a feature of the implementation. (Or, to be even more precise: a feature of the interactions between the implementations of all the languages involved.) In your case, it is not the Python programming language that allows this interoperability, it is the IronPython implementation – you couldn't interoperate between C♯ and Python nearly as easily if you were using CPython or Jython.

Note, however, that a programming language specification may of course demand that all implementations must be interoperable in a certain way.

In general, in order to mix two different programming languages, the programs in those languages must be able to exchange data with each other, as well as affect each other's behavior somehow (e.g. call functions). Let's call the thing that makes it possible for the languages to interoperate the "magic channel".

The more basic and low-level the magic channel is, the more likely it is that the two languages will be able interoperate in some way, but the flip-side is that the interoperation will be of much lower "fidelity". In the worst case, you create two completely separate programs, one program could simply write its output to a file, which is then read and parsed and processed by the other.

The more high-level the magic channel is, the higher-fidelity the interoperability will be. For example, a class in language A can inherit from a class in language B and call methods written in language C. But on the flip-side, the more high-level the magic channel is, the more likely it is that there will be an "impedance mismatch" between the magic channel and one of the languages. Imagine a magic channel which is based on objects, classes, and methods, and now you try to interoperate between Io (which has no classes) and Forth (which has no objects, not classes, and no methods).

Many programming language implementations allow basic interoperability with a subset of the capabilities of the C programming language as their "common magic channel". This is usually called a Foreign-Function Interface (FFI). Since many modern Operating Systems are based around the semantics of C, many programming language implementations are implemented in C or languages that can easily interoperate with it (C++, D, Rust, Go, etc.), a C-based FFI will usually allow interoperability with almost anything. But, it is somewhat low-level.

Programming language implementations that target the Java platform or the CLI platform, usually try to use that platform's native abstractions as their magic channel, which are a bit higher-level than C (e.g. both Java and the CLI have objects, classes, and methods).

Microsoft created the (now mostly abandoned) Dynamic Language Runtime as a way of achieving interoperability at an even higher level. As a little bit of history: IronPython was written by the author of Jython to prove that the CLI was not usable for dynamic languages. Much to his surprise, his early, un-optimized throwaway demo turned out to be not only much faster than he thought but also much faster then Jython, and even faster than CPython. He was later hired by Microsoft, and another person was hired to write an IronRuby implementation. They analyzed the implementation of IronPython and potential requirements of a Ruby implementation (as well as existing Ruby implementations for the CLI such as Ruby.NET), while also keeping an eye on other potential languages like ECMAScript. Then, they extracted parts of IronPython and made them generally re-usable, refactoring IronPython to be built on-top of this newly created so-called Dynamic Language Runtime, at the same time building IronRuby as open-source and the never released proprietary ManagedJS (an implementation of ECMAScript) and Dynamic VB (aka VBx, an implementation of a language that can be viewed as either a modernized continuation of Classic VB6 or a dynamic variant of VisualBasic.NET). Other developers quickly picked up on the DLR, producing e.g. IronJS and IronScheme.

MS demonstrated impressive interoperability between those four languages as well as with other "classic" CLI languages such as C♯ and F♯. Unfortunately, Microsoft completely abandoned ManagedJS and VBx, released IronPython and IronRuby to the community (with IronPython being picked up and IronRuby more or less dead) and also stopped development of the DLR. Now, only the minimal set of features of the DLR required to support C♯ dynamic are still part of .NET, the more full-featured version is maintained as part of IronPython.

In the Java community, there were and are similar projects: dynalang is now mostly dead, but dynalink, which was extracted from Nashorn in a similar vein as the DLR was extracted from IronPython, is alive and well, and is part of Java since Java 9.

A very interesting project is Truffle, which is a framework for easily writing interpreters for programming languages. In general, if those language interpreters are written according to certain interfaces and rules, they will be able to interoperate with each other and with other JVM-based languages (including, but not limited to Java) at a very high level. Truffle currently ships with implementations of Ruby, ECMAScript (including a Node.js compatible library and runtime), R, Python, and very interestingly, LLVM bitcode. Especially when running Truffle on the GraalVM, you get very good support for Polyglot programming.

The Parrot VM was a very ambitious VM and runtime that aimed to be a universal platform for dynamic languages. It was designed by the Perl6 community and intended as the primary target platform for Rakudo. At one time, it had implementations for Perl5, Perl6, Ruby, Python, ECMAScript, Lua, PHP, Scheme, and many others, but none of those were in a production-ready state.

  • Is there enough of the DLR left in .net to practically build a dynamic language with it, or would IronPython's core be a better place to start? – Robert Harvey Jul 15 '19 at 14:03

Many programming languages contain a foreign function interface (FFI), or language bindings as it can also be referred to. There are many native libraries developed for use with Python, Ruby, etc.

Here are a few examples:

There are also projects such as SWIG, Simplified Wrapper and Interface Generator, which can generate these for you.

  • 3
    In addition, many languages and platforms include a C FFI, including .NET. C is sort of the lingua franca of programming language interoperability. – Robert Harvey Jul 12 '19 at 4:10
  • 1
    In Java, we have the (J)ava (N)ative (I)nterface, which allows us to communicate with native applications or libs written in other languages like C, C++ or assembly. – Laiv Jul 12 '19 at 6:08

This mechanism is called a Foreign function call. Pretty much all major programming languages can do it, though the ease of use of a foreign function call differs between each pair of languages implementations.

Python itself for example has ctypes in the standard library and a third party library cffi that allows it to call into any C code, and other languages that exposes a C-like foreign function interface (for which there are quite a lot). Java has JNI (Java Native Interface).

.NET CLR and Java is somewhat different, because they expose an interface whereby any languages running in the same VM can call into any other language in the VM, so foreign function call from within the same runtime is generally pretty straightforward. This is made possible because those languages already have to be mapped into the construct of the VM anyway.


The limit is that a particular combination must be popular enough so that someone can be bothered to implement it. I’m quite sure it is possible to build something that lets you call FORTRAN code from Swift, and I’m also quite sure that nobody will be bothered doing it.

Another limitation is that parameters and return values of functions in the called language must be capable of being meaningfully represented in the calling language.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.