晚了我听说用不同语言编写的应用程序可以调用彼此的函数/子例程。现在,直到最近,我觉得这很自然 - 因为所有,是的 - 这就是我当时的想法,愚蠢的我! - 语言被编译成机器代码,对于所有语言都应该是相同的。只有一段时间后我才意识到,甚至用“更高机器代码”编译的语言 - IL,字节代码等也可以相互交互,实际上是应用程序。我试图找到答案很多次,但失败了 - 没有回答让我满意 - 要么他们认为我对编译器了解很多,要么我完全不同意的事情,以及其他的东西...请在易于理解的方式如何解决。特别是编译成“纯粹”机器代码的语言如何具有不同的称为“调用约定”的东西,这让我抓住了我的头发。
答案 0 :(得分:0)
这实际上是一个非常广泛的话题。编译为机器代码的语言通常可以调用彼此的例程,尽管通常并非没有努力;例如,C ++代码可以在正确声明时调用C例程:
// declare the C function foo so it can be called by C++ code
extern "C" {
void foo(int, char *);
}
这很简单,因为C ++是为与C兼容而明确设计的(它还支持从C调用C ++例程)。
调用约定确实使图片复杂化,因为一个编译器编译的C例程可能无法从另一个编译器编译的C调用,除非它们共享一个公共调用约定。例如,一个编译器可能编译
foo(i, j);
到(伪装配)
PUSH the value of i on the stack
PUSH the value of j on the stack
JUMP into foo
而另一个可能会以相反的顺序推送i
和j
的值,或将它们放在寄存器中。如果编译器按照另一个约定编译foo
,它可能会尝试以错误的顺序从堆栈中获取其参数,从而导致不可预测的行为(如果它立即崩溃,请认为自己很幸运)。
有些编译器为此目的支持各种调用约定。 Wikipedia article引入了呼叫约定;有关更多详细信息,请参阅编译器的文档。
最后,在同一地址空间中混合字节码编译或解释语言和低级语言仍然更复杂。高级语言实现通常带有它们自己的约定集,以使用较低级(C或C ++)代码扩展它们。例如,Java有JNI和JNA。