Skip to content

Working across mixed-language codebases

Real systems are rarely one language. A product might have a C/C++ core, a Java or C# UI, Python tooling, generated web assets, and Fortran or Ada numerics underneath. Tools that only speak one language force you to stitch together a picture by hand. Understand parses all of it into one project database, so entities, calls, and dependencies are cross-referenced across the whole system — including, for many language pairs, calls that cross from one language into another.

One database, many languages

Understand ships parsers for 17+ languages in the same product:

Family Languages
Systems C, C++, Objective-C, Rust, Ada, Fortran, JOVIAL, Pascal, assembly
Managed / app C#, Java, Python, BASIC
Hardware / web VHDL, HTML / CSS / JavaScript

A single project can contain several of these at once. You don't run separate analyses and reconcile them — one analysis populates one database that spans every language present.

Add only the languages you have

A project analyzes the languages it's configured for. See Accurate C/C++ projects and the accuracy cluster for how parsing is configured per language; the filters offered are built from the languages in the project.

Trace across the boundary

Because everything lands in one model, the exploration tools don't care which language an entity is in:

Follow data flow across an interop boundary

The hard seams are the interop boundaries — where a call leaves one language and enters another (Java ↔ JNI ↔ native C/C++, C# P/Invoke, Python C extensions). These are exactly the seams a single-language tool can't see across. Understand links many of them automatically: entities are matched across languages by their externally linkable names, so when the exported name on one side matches the name computed on the other, the call edge appears like any other reference — see how cross-language links are resolved, including the Multiple Language Linkage settings that control the matching. How much links up automatically varies by language pair (and toolchain); not every combination is handled.

When a boundary doesn't link up on its own:

  1. Check the Multiple Language Linkage options for the languages involved — the exported name on one side must match the name Understand computes on the other (combined-language analysis).
  2. Trace the call chain to the boundary function on each side (the native method declaration in Java, the exported implementation in C/C++) with the Information Browser, and jump between the sides by the shared symbol name — find things fast locates the native implementation of a declared boundary function.

Confirm the boundary edge

Cross-language links follow name matching, not the framework's runtime binding. Where the connection lives in reflection or generated stubs, the automatic edge may be missing — confirm the match at the boundary instead of assuming every seam is linked.

Measure and check per language

  • Metrics are computed for every supported language, so you get one consistent complexity and size picture across the codebase.
  • CodeCheck standards are language-specific — see Which standard should I check against? — but they run in the same pass over the same project, so a polyglot codebase is checked in one place.

Visualize the whole system

Graphs draw call and dependency structure across the language boundary too. Start with Which graph should I use? and open a graph.

Mixed-language systems are often also legacy systems — for the full read-map-and-change workflow, see Understanding & reverse-engineering legacy code.