Mixing Languages

Mixing Languages

You don't have to limit yourself to one programming language in a project.

There are several ways (and reasons) to use more than one language and combine logic between them.

Mixing Languages

Mixing multiple languages is relatively easy when working with a VM that has multiple languages implemented. You can generally just import/​call code from another language.

e.g. on the JVM: Java, Scala, Python (Jython), Ruby (JRuby).

e.g. on the .NET CLR: C#, C++, F#, Python (IronPython), Scheme (IronScheme), Visual Basic

e.g. on GraalVM, polyglot code can call between languages (but docs are questionable).

Mixing Languages

Maybe you want to do this for speed: most of your logic can be written in any language you like, but the critical few percent can be written in C/​Go/​Rust for speed.

Foreign Function Calls

For example, suppose I want to call a C function from Python. SWIG provides some tools to call C/C++ code from several other languages.

First: write the C header and implementation in the usual way: example.h, example.c.

For this example, two simple functions:

int fact(int n);
int escapes(double cr, double ci, int it);

Foreign Function Calls

Create a SWIG interface file so it can figure out what you want available in Python: example.i.

Compile it so it can be loaded as a Python module. Then it works just like any other Python module.

import example
print(example.fact(10))

Usage: fact.py, mandel.py.

Foreign Function Calls

Bridging C and Python could also have been done with Cython or CFFI or a Python C extension.

In general, look for a foreign function interface (FFI) for your language.

Foreign Function Calls

Another scenario to mix languages: you want to call a library that's available in another language: there is no equivalent in the language you're using, and it would be too much work to re-write it.

A foreign function interface could take care of this problem, but we'll try another solution…

Remote Procedure Calls

As another example: translating Github-flavoured markdown to HTML. This differs slightly from plain markdown (that many languages have libraries for) and the canonical implementation is Ruby-only.

Remote Procedure Calls

This time, we will use a remote procedure call to talk to the other language. As long as both sides of the conversation agree on an RPC protocol, everything should work.

This could be a REST or Thrift or XML-RPC or ZeroMQ or other RPC technologies.

Remote Procedure Calls

I'm going to use RabbitMQ (a message queue tool) to send requests/​responses between two languages because it supports many language and has some nice tutorial code that I can use to cheat.

Remote Procedure Calls

We are essentially creating a microservice. The idea: relatively small pieces of logic are implemented as services which can be accessed with a network request (often HTTP, but RabbitMQ here).

This forces components to have very clearly defined interfaces and not be deeply linked. It also means that different components can be implemented with different technologies (including programming language).

Remote Procedure Calls

In Ruby, we need an RPC server: it will listen for messages coming in on a queue. When they arrive, do the Markdown conversion, and send the result back on the channel for the response.

The code: rpc_server.rb. Start it with:

ruby rpc_server.rb

Remote Procedure Calls

The Python client needs to send the Markdown message, and then wait for the HTML to be returned on the result channel. Once the appropriate class is defined, calling it is just:

markdown_rpc = MarkdownRpcClient()
response = markdown_rpc.call("## Hello world\n\nGreetings.")
print(response)
<h2>Hello world</h2>
<p>Greetings.</p>

The code: rpc_client.py.

Remote Procedure Calls

If everything has gone well, we should be able to make the same RPC call from any supported language. In Go, more setup but then:

res, err := markdownRPC("## Hello world\n\nGreetings.")
if err != nil {
	panic("Failed to handle RPC request")
}
fmt.Println(res)
<h2>Hello world</h2>
<p>Greetings.</p>

The code: rpc_client.go.

Summary

It's easier to mix languages in a single project than you might have thought. There is some setup work to do, but after that, interacting between languages is fairly straightforward.

Modern software projects often use multiple languages in their implementation. Modern tools support this.