Errors: Coping With Multiple Languages

From Matt Morris Wiki
Jump to navigation Jump to search

Programming - Errors


Introduction

Nowadays, lots of applications use many different languages.

Think of a derivatives trading platform: mathematical routines in C++, middleware in Java, a front end in C#, and COM automation in VB/VBA.

Think of a first-person shooter game: low-level graphics routines in C++, and alternating levels of a scripting language and C++ to aid construction of strategies.

But how should you deal with errors where multiple languages are in use?

Calling Non-Garbage-Collected Languages From Garbage-Collected Ones

You have to be careful with garbage-collected languages (eg C#, Java) calling libraries in non-garbage-collected languages (eg C++).

This is because there will be a certain degree of "idiom mismatch" between the two languages. In particular, it will be surprisingly easy to leak resources when exceptions are thrown, since the non-garbaged-collected language references will not have any "backstop" in the surrounding language to ensure things get freed in finalizers.

Dispose the non-collected resources explicitly, and at only a few well-defined points

Don't rely on objects going out of scope and being collected to trigger the release of underlying resources.

Instead call disposal routines explicitly in "finally" clauses, and organise code so that the non-collected resources are disposed at as few points as possisble.

Track the non-collected resources

You will almost certainly get a leak of non-collected resources appearing at some point.

You should build in tracking for such resources from the start, so you are not faced with leakage problems in production that you cannot diagnose.

Getting Information Across The Language Boundary

Translate Exceptions To Exceptions

Programming with multiple languages is often viewed as a dark science. People will do the minimum to get the functionality they need, and then move on. One area that typically suffers is error propagation. In particular, a library that throws exceptions will be wrapped by routines in another language that only return numeric status codes, or boolean values.

This particular short-cut should be avoided. It loses just as much information as swallowing exceptions in a single language does. Libraries wrapped in this fashion will prove hard to debug - indeed, a lack of thought given to error propagation is a major reason why cross-language programming has an undeservedly "difficult" reputation.

Most languages provide an API to allow construction and throwing of exceptions by other languages. When transferring from one language to another, translate the exception at the boundary to look like a natural exception for the language that you are entering. Make sure that you use a central translation routine, so that this mapping is only done once.

Here are the starting points for learning how to throw exceptions from native code in various languages:

  • Java provides the Java Native Interface
  • Python provides the PyErr_* functions
  • .NET languages such as C# and VB.NET provide the System.Exception class
  • COM (and so VB/VBA) provides the IErrorInfo interface, which ATL programmers can access via the AtlReportError() function, and which any programmer can access via the CreateErrorInfo() function.

Preserve What Information You Can

When translating, you may have no choice but to lose some information. For instance, if a calling language does not support nested exceptions, how should it deal with a nested exception from code it has invoked in another language?

In such cases, you will have to use your judgement. Give priority to the part of the exception's information that will be of most use to the calling code. One possibility for nested exceptions would be to combine the various descriptions into a single error string.

Have A "Catch-All" Clause At The Language Boundary

Just before you leave one language and enter another, you have a final chance to test for uncaught exceptions. Use this chance, and add a "catch-all" clause before exit. You might not be able to provide any information about the nature of the error, but you will at least be able to alert the calling language that an exception was pending.