遅くなって、異なる言語で書かれたアプリケーションがお互いの関数/サブルーチンを呼び出すことができると聞いていました。さて、最近まで、それは非常に自然なことだと感じていました。-言語はマシンコードにコンパイルされ、すべての言語で同じである必要があります。ほんの少し前に、「より高いマシンコード」でコンパイルされた言語(IL、バイトコードなど)でさえ、実際にはアプリケーションが相互に対話できることに気づきました。私は何度も答えを見つけようとしましたが、失敗しました-答えは私を満足させませんでした-彼らは私がコンパイラについてたくさん知っていると思ったか、私が完全に同意しなかった何か、そして他のもの...で説明してくださいこれがどのように機能するかを理解するのは簡単です。特に言語が「純粋な」にコンパイルされる方法
1 に答える
これは実際には非常に幅広いトピックです。機械語にコンパイルされた言語は、通常は努力なしではありませんが、多くの場合、互いのルーチンを呼び出すことができます。たとえば、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);
to(疑似アセンブリ)
PUSH the value of i on the stack
PUSH the value of j on the stack
JUMP into foo
i
一方、別の人はとの値をj
逆の順序でプッシュしたり、レジスタに配置したりする場合があります。別の規則に従ってコンパイラーによってコンパイルされた場合foo
、その引数を間違った順序でスタックからフェッチしようとする可能性があり、予期しない動作につながる可能性があります(すぐにクラッシュする場合は幸運だと考えてください)。
一部のコンパイラは、この目的のためにさまざまな呼び出し規約をサポートしています。ウィキペディアの記事では、呼び出し規約を紹介しています。詳細については、コンパイラのドキュメントを参照してください。
最後に、バイトコードでコンパイルまたはインタプリタされた言語と下位レベルの言語を同じアドレス空間で混合することはさらに複雑です。高水準言語の実装には通常、低水準(CまたはC ++)コードで拡張するための独自の一連の規則が付属しています。たとえば、JavaにはJNIとJNAがあります。