> I can't seem to understand the reason as to why multiple programming languages are used in the same product or software?

It is quite simple: there is no single programming language suitable for all needs and goals.

Read Scott's book [*Programming Languages Pragmatics*][1]

Some programming languages favor expressiveness and [declarativity][2] (a lot of scripting languages, but also high-level programming languages like [Agda][3], [Prolog][4], [Lisp][5], Haskell, Ocaml, ...). When the cost of development is important (human time and cost of developers), it is suitable to use them (even if the runtime performance is not optimal).

Other programming languages favor run-time performance (many low-level languages, with usually compiled implementations, like C++, Rust, Go, C, assembler, also specialized languages like OpenCL ...); often their specification allows some [undefined behavior][6]. When the performance of the code matters, it is preferable to use these languages.


Some external [libraries][7] are written in and for a particular language and [ABI][8] and [calling conventions][9] in mind. You may need to use that other language, and follow [foreign function interface][10] conventions, perhaps by writing some [glue code][11].

In practice, it is unlikely to have a programming language which is highly expressive (so improves the productivity of the developer, assuming a skilled enough developer team) and very performant at runtime. In practice, there is a trade-off between expressivity and performance.

**Note:** however, there has been some *slow* progress in programming languages: Rust is more expressive than C or perhaps even C++ but its implementation is almost as performant, and probably will improve to generate equally fast executables. So you need to learn new programming languages during your professional life; however there is [*No Silver Bullet*][12]

Notice that the cost of development is more and more significant today (that was not the case in the 1970s -at that time computers where very costly- or in *some* embedded applications -with large volume of product). The rule of thumb (very approximate) is that a skilled developer is able to write about 25 thousand lines of (debugged & documented) source code each year, and that does not depend much on the programming language used.


A common approach is to embed some [scripting language][13] (or some [domain specific language][14]) in a large application. This design idea (related to domain-specific language) has been used for decades (a good example is the [Emacs][15] source code [editor][16], using Elisp for scripting since the 1980s). Then you'll use an easily embeddable interpreter (like [Guile][17], [Lua][18], [Python][19], ...) inside a larger application. The decision to embed an interpreter inside a large application has to be done very early, and has strong architectural implications. You'll then use two languages: for low level stuff which has to run quickly, some low level language like C or C++; for high level scripts, the other DSL or scripting language.


Notice also that a given software can run, within most current [operating systems][20] (including Linux, Windows, Android, MacOSX, Hurd, ...), in several cooperating [processes][21] using some kind of [inter-process communication][22] techniques. It can even run on several computers (or many of them), using [distributed computing][23] techniques (e.g. [cloud computing][24], HPC, client server, [web applications][25], etc...). In both cases, it is easy to use several programming languages (e.g. code each program running on one process or computer in its own programming language). Read [*Operating Systems: Three Easy Pieces*][26] for more. Also, [foreign function interfaces][10] (e.g. [JNI][27]), [ABI][8]s, [calling conventions][9], etc... facilitate mixing several languages in the same program (or [executable][28]) - and you'll find code generators like [SWIG][29] to help.

In some cases, you *have to* mix several programming languages: web applications need Javascript or Webassembly (the only languages running inside most web browsers) for the part running in the browser (there are frameworks *generating* these, e.g. [ocsigen][30]). Kernel code need some stuff (e.g. the scheduler, or the low level handling of interrupts) to be partly written in assembler, because C or C++ cannot express what is needed there, etc....
Some languages are designed to facilitate such a mixture (e.g. [`asm` statements][31] in C, [code chunks][32] in my late [GCC MELT][33], etc...).

In some cases, you use [metaprogramming][34] techniques: some parts of your large software project would have code (e.g. in C or C++) generated by other tools (perhaps project specific tools) from some ad-hoc formalization: parser generators (improperly called compiler-compilers) like [bison][35] or [ANTLR][36] come to mind, but also SWIG or RPCGEN. And notice that [GCC][37] has more than a dozen of specialized C++ code generators (one for every internal DSL inside GCC) inside it. See also [this][38] example. Notice that [metabugs][39] are hard to find. Read also about [bootstrapping compilers][40], and about [homoiconicity][41] and [reflection][42] (it is worthwhile to learn [Lisp][5], play with [SBCL][43], and to read [SICP][44]; look also into [JIT-compiling][45] libraries like [GCCJIT][46]; in some large programs you might generate some code at runtime using them; be aware of [Greenspun's tenth rule][47]). Look also into the [*Circuit Less Traveled*][48] talk at FOSDEM2018.

Sometimes, you want to provide formal annotations of your code (e.g. to help provers, static analyzers, compilers), using some specialized annotation language (which might be viewed as some DSL). Look into [ACSL][49] with [Frama-C][50] to annotate C programs (safety-critical ones), or [OpenMP][51] pragmas for HPC. Caveat: writing such annotations can require a lot of skills and development time.

BTW, this suggests that some skills about compilers and interpreters are useful for every developer (even without working inside compilers). So read the [Dragon Book][52] even if you don't work on compilers. If you code your own interpreter (or if you design your DSL), read also [*Lisp In Small Pieces*][53].

See also [this][54] & [that][55] & [that][56] & [that][57] answers of mine related to your question.

Study also the source code of several large [free software][58] projects (on [github][59] or from your [Linux distribution][60]) for inspiration and enlightenment.

**PS:** there are also social or organizational or historical reasons to mix programming languages; I'm ignoring them here, but I know that in practice such reasons are dominant. Read also [*The Mythical Man Month*][61]


  [1]: https://www.cs.rochester.edu/~scott/pragmatics/
  [2]: https://en.wikipedia.org/wiki/Declarative_programming
  [3]: https://en.wikipedia.org/wiki/Agda_(programming_language)
  [4]: https://en.wikipedia.org/wiki/Prolog
  [5]: https://en.wikipedia.org/wiki/Lisp_(programming_language)
  [6]: https://en.wikipedia.org/wiki/Undefined_behavior
  [7]: https://en.wikipedia.org/wiki/Library_(computing)
  [8]: https://en.wikipedia.org/wiki/Application_binary_interface
  [9]: https://en.wikipedia.org/wiki/Calling_convention
  [10]: https://en.wikipedia.org/wiki/Foreign_function_interface
  [11]: https://en.wikipedia.org/wiki/Glue_code
  [12]: https://en.wikipedia.org/wiki/No_Silver_Bullet
  [13]: https://en.wikipedia.org/wiki/Scripting_language
  [14]: https://en.wikipedia.org/wiki/Domain-specific_language
  [15]: https://www.gnu.org/software/emacs/
  [16]: https://en.wikipedia.org/wiki/Source_code_editor
  [17]: https://www.gnu.org/s/guile/
  [18]: http://lua.org/
  [19]: https://docs.python.org/3/extending/index.html
  [20]: https://en.wikipedia.org/wiki/Operating_system
  [21]: https://en.wikipedia.org/wiki/Process_(computing)
  [22]: https://en.wikipedia.org/wiki/Inter-process_communication
  [23]: https://en.wikipedia.org/wiki/Distributed_computing
  [24]: https://en.wikipedia.org/wiki/Cloud_computing
  [25]: https://en.wikipedia.org/wiki/Web_application
  [26]: http://pages.cs.wisc.edu/~remzi/OSTEP/
  [27]: https://en.wikipedia.org/wiki/Java_Native_Interface
  [28]: https://en.wikipedia.org/wiki/Executable
  [29]: http://swig.org/
  [30]: http://ocsigen.org/
  [31]: https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html
  [32]: http://starynkevitch.net/Basile/gcc-melt/MELT-Starynkevitch-DSL2011.pdf
  [33]: http://starynkevitch.net/Basile/gcc-melt
  [34]: https://en.wikipedia.org/wiki/Metaprogramming
  [35]: https://www.gnu.org/software/bison/
  [36]: http://www.antlr.org/
  [37]: http://gcc.gnu.org/
  [38]: https://stackoverflow.com/a/49829773/841108
  [39]: http://bootstrappingartificialintelligence.fr/WordPress3/2014/06/the-meta-bug-curse-of-the-bootstrap/
  [40]: https://en.wikipedia.org/wiki/Bootstrapping_(compilers)
  [41]: https://en.wikipedia.org/wiki/Homoiconicity
  [42]: https://en.wikipedia.org/wiki/Reflection_(computer_programming)
  [43]: http://sbcl.org/
  [44]: https://mitpress.mit.edu/sicp/
  [45]: https://en.wikipedia.org/wiki/Just-in-time_compilation
  [46]: https://gcc.gnu.org/onlinedocs/jit/
  [47]: https://en.wikipedia.org/wiki/Greenspun%27s_tenth_rule
  [48]: https://fosdem.org/2018/schedule/event/alternative_histories/
  [49]: https://frama-c.com/acsl.html
  [50]: http://frama-c.com/
  [51]: https://en.wikipedia.org/wiki/OpenMP
  [52]: https://en.wikipedia.org/wiki/Compilers:_Principles,_Techniques,_and_Tools
  [53]: https://en.wikipedia.org/wiki/Lisp_in_Small_Pieces
  [54]: https://softwareengineering.stackexchange.com/a/277229/40065
  [55]: https://softwareengineering.stackexchange.com/a/339948/40065
  [56]: https://softwareengineering.stackexchange.com/a/288144/40065
  [57]: https://softwareengineering.stackexchange.com/a/307685/40065
  [58]: https://en.wikipedia.org/wiki/Free_software
  [59]: http://github.com
  [60]: https://en.wikipedia.org/wiki/Linux_distribution
  [61]: https://en.wikipedia.org/wiki/The_Mythical_Man-Month