D言語対Cのインタフェース



Cのインタフェースに対して設計に従って、Dは目標システム上のCとよく協力すべきである.Dは、ターゲット環境上のCランタイムライブラリに依存し、標準仮想マシンが欠けているいくつかの欠陥を多少補償します.既存のC APIをDで書き換えるか、Dでカプセル化するかは意味がない.直接呼び出すのはずっと簡単ではありませんか?!
Cコンパイラと同じデータ型、メモリ分散、関数呼び出し/戻り命令シーケンスを採用すれば、そうすることができます.
C関数Dを呼び出すと、直接C関数を呼び出すことができる.カプセル化関数,パラメータ変換は不要であり,C関数も個別のDLLに入れる必要はない.
C関数は、「C」呼び出し規則を使用すると宣言する必要があります.たとえば、次のようにします.
	 (C)  strcmp( *string1,  *string2);
	
は、Dコードで自然に呼び出すことができます.
	 std.string;
	 myDfunction([] s)
	{
	     strcmp(std.string.toCharz(s), );
	}
	
次の点に注意してください.
  • Dは、C関数名の変換規則および関数の呼び出し/戻り命令シーケンスを知る.
  • C関数は、同じ名前の別のC関数によって再ロードできません.
  • Dには次のようなものはありません.cdecl、__far、__stdcall、__declspecとかそういうCタイプの修飾子.これらの機能はextern(C)のような「特徴」によって実現される.
  • Dにはconstまたはvolatileタイプ修飾子はありません.これらのタイプの修飾子を使用するC関数を宣言する場合は、これらのキーワードを宣言から削除するだけです.
  • Dの文字列は0で終わりません.「データ型互換性」を参照してください.

  • したがって、D関数がCコンパイラと互換性のある特徴を採用している限り、最も可能性のあるのはextern(C)であり、CコードはD関数を呼び出すこともできる.
    	
    	 (C)
    	{
    	     myfunc( a,  b)
    	    {
    		...
    	    }
    	}
    	

    メモリ割り当てCコードは、malloc()とfree()を呼び出してメモリを表示して管理する.Dゴミ収集プログラムを使用してメモリを割り当てるので、メモリを明示的に解放する必要はありません.
    Dは依然としてc.stdlibを使用することができる.malloc()とc.stdlib.free()はメモリを明示的に割り当て、解放し、mallocバッファが必要なC関数などをリンクするために使用することができる.
    収集プログラムに割り当てられたメモリへのポインタがC関数に渡される場合は、そのメモリがC関数を使用して終了する前にメモリ収集プログラムによって回収されないことを確認する必要があります.この目的を達成するには、次のようにします.
  • c.stdlibを使用する.malloc()は、データのコピーを作成し、そのコピーをC関数に渡します.
  • は、ゴミ収集プログラムがスタックをスキャンするため、パラメータまたは自動変数としてポインタをスタックに配置します.
  • は、ゴミ収集プログラムが静的データセグメントをスキャンするため、そのポインタを静的データセグメントに配置する.
  • はgcを用いる.addRoot()またはgc.addRange()は、ゴミ収集プログラムによって管理されるポインタを渡します.

  • 割り当てられたメモリブロックの内部へのポインタでも、GCがオブジェクトが使用されていることを知るのに十分です.つまり、割り当てられたメモリの先頭へのポインタを維持する必要はありません.
    ゴミ収集プログラムは、D Threadインタフェースによって作成されたスレッドではないスタックをスキャンしたり、他のDLLのデータセグメントなどをスキャンしたりしません.
    データ型互換性
    Dタイプ
    Cタイプ
    void
    void
    bit
    無等価タイプ
    byte
    signed char
    ubyte
    unsigned char
    char
    char(Dのcharsは符号なし)
    wchar
    wchar_t
    short
    short
    ushort
    unsigned short
    int
    int
    uint
    unsigned
    long
    long long
    ulong
    unsigned long long
    float
    float
    double
    double
    extended
    long double
    imaginary
    long double _Imaginary
    complex
    long double _Complex
    type*
    type *
    type[dim]
    type[dim]
    type[]
    無等価タイプ
    type[type]
    無等価タイプ
    "string/0"
    「string」またはL「string」
    class
    無等価タイプ
    type(*)(parameters)
    type(*)(parameters)
    ほとんどの32ビットCコンパイラでは、上記の対応関係が成り立っています.C規格はタイプの大きさを制約しないので、この対応関係を使用するときは特に注意してください.
    printf()を呼び出す主な問題は、printfフォーマットインジケータが対応するDデータ型にどのように一致するかである.設計によればprintfは0で終わる文字列しか処理できず,Dのchar動的配列は処理できないが,D動的配列の構造が{長さ,データへのポインタ}であるためprintfの
    %.*sフォーマットはよく機能しています.
    	 foo([] string)
    	{
    	    printf(, string);
    	}
    	
    機敏な読者はprintf形式の文字列の文字量が'/0'で終わらないことに気づくだろう.これは、文字列の文字量がデータ構造の初期値でない場合、最後に補助的な'/0'が格納されるためです.
    構造と結合Dの構造と結合はCにおけるものと類似している.
    Cコードは、通常、コマンドラインオプションまたは様々なインプリメンテーションによって提供されるpragmaコマンドを使用して、構造の整列または緊縮方法を指定する.Dは、Cコンパイラ規則に対応する明示的な位置合わせ特徴をサポートする.Cコードがどのように整列しているかを確認してから、D構造の整列方法を明示的に設定することができます.
    Dビットドメインはサポートされていません.必要に応じて、シフトとmask操作を使用してシミュレーションを行うことができます.
    C++のインタフェースDには、C++のインタフェースは提供されない.ただし,DはCに対するインタフェースを提供するので,Cリンクを用いたC++関数にアクセスできる.
    DのクラスオブジェクトはC++のクラスオブジェクトと互換性がありません.