Calling foreign code can be a broad subject.
Typically, when folks talk about calling foreign code it's almost always from the X Langauge to the C language, as C is the ubiquitous systems programming language across most platforms. So, a big draw for X->C is to call system runtimes, such as Unix file I/O or Windows GUI functions, most all of which are published as C libraries.
Since many languages are themselves written in C, it makes even more sense to be able to invoke C routines from the language runtime.
What you typically won't find is something like a Lua -> Haskell, or Python -> Ruby.
When a language calls a C function, that function needs to be linked into the running image. This linking is typically done through a dynamic library (DLL in Windows, Shared Library in Unix). Dynamic modules have the advantage of being, well, dynamic! Meaning the language runtime doesn't necessarily need specific information about library when the runtime is originally created. It can do everything later, after it's built.
But this is why you see many times some Python library needing not just Python, but some other project. This is so that you can be sure that the shared library from the project is available when the Python code goes to look for it.
For languages other than C, the mechanics are typically different. If you want to call Python from Ruby, you're probably better off firing off a Python sub process, and then talking to it via a pipe or a socket. But that can be quite expensive.
Other things you can do is you can embed one language into another. For example, you can embed Python in C, that is the C program can invoke Python code. Well, since you can invoke Python from C, and can call C from Ruby, well then Ruby -> C -> Python. The C code acts as a bridge.
There are a lot of reasons to not do this, it's expensive, it can be problematic, having two conflicting high level language runtimes fighting each other. But, it's possible.
Other compiled languages, like Pascal or Fortran, can more easily call or be called from C. This is because their compiled machine language routines tend to have little overhead. But there are other problems that need to be addressed.
For example Pascal and C historically have different calling conventions. At a minimum, they pass arguments to stack in a different order. But also, things like strings are represented differently, and who knows how other internal things are represented. All manageable, and many modern implementations of cognizant of living in a mixed language environment. In Pascal, you can add an option that a particular routine is a C routine so the compiler can juggle the parameters properly. Similarly, some C compilers can do the same thing with Pascal. This was much more prevalent in the past when Pascal was more popular. The original Macintosh libraries were all written to work with Pascal, so Mac C compilers had this capability.