2016-03-25 22 views
0

AdaバインディングアプリケーションでCからAdaに構造体を渡す必要があります。したがって、私はAdaとCの両方の構造を宣言し、両方のソース側が構造の構成を解読できるようにしました。CからAdaへの構造体の受け渡し

Cで

、エイダで

typedef struct { 
    int Status_Code; 
    int Error_Code; 
} Edit_Result_Type; 

type Edit_Result_Rec_Type is 
    record 
     Status  : Integer; 
     Error_Code : Integer; 
    end record; 

pragma Convention (Convention => C, 
        Entity  => Edit_Result_Rec_Type); 

for Edit_Result_Rec_Type use 
    record 
    Status  at 0 range 0 .. 31; 
    Error_Code at 0 range 32 .. 63; 
    end record; 

type Edit_Result_Rec_Type_Ptr is access all Edit_Result_Rec_Type; 

私が参照によって呼び出しを通してCからエイダの構造を渡していたとき、私が知りたかった:

  1. Adaで(上記のように-)構造体の「すべてアクセス」ベクトル型を宣言しても構いません。 Ada関数の仮パラメータとして直接使用します。例:

    procedure Process_Data (Edit_Result_Ptr : in out Edit_Result_Rec_Type_Ptr) is 
    begin 
        Edit_Result_Ptr.Status  := 1; 
        Edit_Result_Ptr.Error_Code := 0; 
    end Process_Data; 
    

    このアプローチは致命的ですか?私はそれが知っている、ちょうど "どのように"深さを知りたい!

  2. 他の(より良い)アプローチで参照渡しを行う方法はありますか?私はそれを "System.Address"パラメータとして渡し、Ada関数内のローカルベクトルのEdit_Result_Rec_Type_Ptrに "チェックされていない変換"を行い、レコードメンバーを読み書きすることができますか?このアプローチには致命的な問題がありますか?

+3

あなたは何を意味するのかわかりません。 Cは**厳密には**値による呼び出しです。 – Olaf

+2

はい、まさに! Cは参照を提供しません。オブジェクトのアドレスをポインタに渡すことはできますが、ポインタも値渡しになります。 – Olaf

答えて

6

エイダとCをインタフェースするとき、あなたは本当にが言うRM、附属書B.3、読んでください:他、任意のモードの

をレコードタイプTのエイダパラメータを、慣例C_Pass_By_Copyの型のinパラメータよりも、*引数でC関数にが渡されます。ここで、tはAda型Tに対応するC構造体です。

だから、あなたの手順では、単に実行します。

procedure Process_Data (Edit_Result : in out Edit_Result_Rec_Type) is 
begin 
    Edit_Result.Status  := 1; 
    Edit_Result.Error_Code := 0; 
end Process_Data; 

pragma Export(C, Process_Data); 

を(またはアスペクトを使用し、2012エイダIF)言われていること

、あなたはするべきでありませんあなたのレコード定義にIntegerを使用しないと、Interfaces.C.intは行く方法です:

周り

    働くだろう
  1. が、なぜ混乱:

    type Edit_Result_Rec_Type is 
        record 
         Status  : Interfaces.C.int; 
         Error_Code : Interfaces.C.int; 
        end record; 
    
    お使いのプラットフォーム上でC int型と一致します

    ご質問については

    (と仮定し、あなたのCコンパイラは、Adaのコンパイラと互換性があります)ポインタで?

  2. いいえ、動作しません.Adaのアクセスタイプ(およびアクセス値)はアドレスではありません。System.Addressをアクセス値に変換するにはSystem.Address_To_Access_Conversionsが必要ですが、もう一度、なぜポインタを使いこなすのでしょうか?

+0

したがって、シグニチャーを持つプロシージャーを次のように使用するとします。 'procedure Process_Data(Edit_Result:in Edit_Result_Rec_Type)は'です。 struct変数のアドレスをcまたはstruct変数自体から渡すべきですか? –

+1

Cの定義はt * – egilhh

+0

ありがとう!、 あなたは(あなたが回答で与えた)あなたのアプローチを使うことの安全面についてコメントすることができますか?そして、それがどんな致命傷を負うかどうか? System.Addressを関数の** in **パラメータとして使用し、** unchecked conversion **を** Edit_Result_Rec_Type **のアクセスに使用すると、どのように安全でないのですか?それは働いた! –

関連する問題