2012-02-07 10 views
3

ウィキによると:異なるプログラミング言語と呼び出し規則

異なるプログラミング言語が異なる呼び出し規約を使用し、 そうすることができ、異なるプラットフォーム(CPUアーキテクチャ+オペレーティングシステム)。だから私は、私はPythonで(.soは/ .dllファイルからエクスポートされた)C/C++関数を呼び出す際には注意することになっています 複数の言語

で書かれたモジュールを組み合わせると、この は時々問題を引き起こすことができますか? はいの場合は、どうすればよいですか? PythonはCで書かれていない少なくともので

問題はより多くの問題時に複数がある説明 - あなたは、一般的には何も心配する必要はありませんので、PythonとCの間の呼び出し

+0

あなたは、PythonからC++の関数を呼び出すために使用しているどのようなユーティリティ? – Lalaland

+0

@EthanSteinberg、おそらくctypes。 – Alcott

答えて

4

Pythonインタプリタ自体がC言語で記述されているため、Cコードと同じ呼び出し規約を使用するため、呼び出し規約はPythonからC言語を呼び出すときには問題になりません。

異なるコンパイル言語(CやAdaなど)で記述されたコードを組み合わせると問題になります。

通常、Cはシステムプログラミング言語であり、したがって標準です。これは、任意の言語のコンパイラが、Cと相互運用するための特殊なサポートを一般に持つことを意味します。CとAdaの相互運用性の例については、hereを参照してください。特別なサポートがない場合、ラッパーはアセンブリレベルで記述する必要があります。

PythonからC++/Adaを呼び出す必要がある場合は、2つの手順に従わなければなりません。最初のステップは、C++/Ada関数のまわりにCラッパーを書くことです。 2番目のステップは、PythonからCラッパーを呼び出すことです。

たとえば、次のC++クラスを取ります。

class Foo 
{ 
public: 
    Foo(); 
    int bar(); 
    ... 
}; 

あなたはパイソンが利用できるようにしたい場合は、まずCでそれをラップする必要があります。

extern "C" { 
typedef void *FooPtr; 
FooPtr foo_new() { return (FooPtr)new Foo(); } 
int foo_bar (FooPtr foo) { return ((Foo*)foo)->bar(); } 
... 
} 

次に、あなたのpythonからのことを呼び出すことができます。 (実際には、Boost.Pythonのように、これを自動化するツールがあります。

ラッパーの記述には、呼び出し規約の変換と型表現間の変換という2つの側面があります。後の部分は通常、最も基本的なタイプの言語を超えてすぐに同等のタイプの表現が非常に異なる傾向があるため、最も困難です。

+0

私はCからAdaに電話すれば、どのように気をつけて、どうすればいいですか? – Alcott

5

は、問題の解決策でありますプラットフォーム上の言語はすべて独立して開発され、アセンブラから個別にブートストラップされます。たとえば、CとFORTRAN、CとPascalの間で、これらの3つの言語のすべてが大雑把なものとして共存している時に呼び出す問題が有名でした。古いMac Toolboxは、主にPascal呼び出し規約を使用してアセンブラで書かれていましたが、初期のアプリケーション開発者はBorland Pascalを使用していました。しかし、SymatecのTHINK CのようなCコンパイラが登場し、それらのプログラマは、引数の型や文字列の規則をどのように翻訳するかを心配しなければなりませんでした(パスカル文字列は最初は長さバイトを持ち、C文字列は最後に0を返します)。

0

CとC++には異なる呼び出し規約があります。 CはC++関数の呼び出しをサポートしていませんが、C++関数の呼び出しをサポートしており、C++のC関数の実装をサポートしています。つまり、C++で関数をextern "C"と宣言することができます。私はPythonバインディングがC++をどのように呼び出しているのかわかりませんが、それぞれの呼び出し規約でCとC++関数を呼び出すように注意する必要があります。一般に、Cの呼び出し規約は、異なる言語間で呼び出すときに使用されます。これは、C++スタイル関数のCスタイル規則を使用してラッパー関数を記述する必要がある可能性があることを意味します。

+1

あなたが参照しているのは、呼び出し規約ではなく、リンクに使用される名前のマングリングです。 – grieve

+0

いいえ、それは**私が言及しているものではありません!関数の呼び出し規約は、CとC++で異なる場合があります。私が話していることについては、7.5 [dcl.link]を参照してください。 –

+0

はい、それは混乱しています。CでC++呼び出しをラップする典型的な理由は、呼び出し規約のためではなく、名前のマングリングのためです。いくつかのコンパイラでは、関数の呼び出し規約を宣言することができ、それはその規約に合わせてコンパイルされます。これは、通常、標準Cとは異なる呼び出し規約でコンパイルされた共有ライブラリとの互換性のために使用されます。 – grieve

0

呼び出し規約は、結果のアセンブリで関数呼び出しがどのように生成されるかを示します。 1つの規則は、呼び出し側がローカル変数のスタック領域の作成とクリーンアップを担当することです。もう1つの規則は、呼び出された関数がローカル変数のスタック領域を作成してクリーンアップすることです。どちらを使うかは問題ではありませんが、明らかに一致するかスタックが壊れてしまいます。

あなたはここで詳細を見ることができます:http://en.wikipedia.org/wiki/Calling_convention

関連する問題