2016-03-25 5 views
0

Ich muss eine Struktur von C nach Ada in einer Ada-Bindeanwendung übergeben. Daher habe ich die Struktur sowohl in Ada als auch in C so deklariert, dass beide Quellseiten die Strukturzusammensetzung entschlüsseln können.Struktur von C nach Ada übergeben

In C

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

In Ada,

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; 

Wenn ich die Struktur von C nach Ada durch Bezugnahme durch Anruf bin vorbei, wollte ich wissen:

  1. Ist es in Ordnung, wenn ich in Ada und. Einen "Access all" - Vektortyp für die Struktur deklariere (wie oben - Edit_Result_Rec_Type_Ptr)? verwende es direkt als formalen Parameter in der Ada-Funktion. Für zB:

    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; 
    

    Ist dieser Ansatz FATAL? Ich weiß es ist, wollte nur "wie" in der Tiefe wissen!

  2. Gibt es noch andere (bessere) Ansätze zum Durchlaufen von Call by Reference? Ich glaube, ich kann es als "System.Address" -Parameter übergeben und eine "ungeprüfte Konvertierung" in Edit_Result_Rec_Type_Ptr in einem lokalen Vektor innerhalb der Ada-Funktion und dann lesen/schreiben Datensatzmitglieder? Hat dieser Ansatz Todesopfer?

+3

Nicht sicher, was Sie meinen. C ist ** strikt ** Aufruf nach Wert. – Olaf

+2

Ja, genau! C bietet keine Referenzen. Sie können die Adresse eines Objekts an einen Zeiger übergeben, aber der Zeiger wird auch als Wert übergeben. – Olaf

Antwort

6

Wenn Ada und C Schnittstelle, sollten Sie wirklich lesen Sie die RM, Anhang B.3, die sagt:

Ein Ada-Parameter eines T-Satztyp, von einem beliebigen Modus, andere als ein in-Parameter einer Art Konvention C_Pass_By_Copy wird als * Argument an eine C-Funktion übergeben, wobei t die C-Struktur ist, die dem Ada-Typ T entspricht.

in Ihrer Prozedur So, gerade tun:

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; 

und

pragma Export(C, Process_Data); 

(oder den Aspekt verwenden, wenn Ada 2012)

aber sagen, dass shouldn Sie Verwenden Sie Integer nicht in Ihrer Datensatzdefinition, Interfaces.C.int ist der Weg zu gehen:

type Edit_Result_Rec_Type is 
    record 
     Status  : Interfaces.C.int; 
     Error_Code : Interfaces.C.int; 
    end record; 

, die die C int auf Ihrer Plattform übereinstimmen (vorausgesetzt, Ihr C-Compiler ist mit dem Ada-Compiler kompatibel)

Was Ihre Fragen:

  1. das funktionieren würde, aber warum mess around mit Zeigern?

  2. Nein, das würde nicht funktionieren, Zugriffstypen (und Zugriffswerte) in Ada sind keine Adressen.Die Konvertierung von System.Address in einen Zugriffswert erfordert System.Address_To_Access_Conversions, aber warum sollte man sich mit Zeigern herumschlagen?

+0

Also wenn Sie sagen, um die Prozedur mit der Signatur zu verwenden: 'Prozedur Process_Data (Edit_Result: in out Edit_Result_Rec_Type) ist '. Sollte ich die Adresse der Strukturvariable aus c oder die Strukturvariable selbst übergeben? –

+1

die C-Definition sollte t * – egilhh

+0

Thanks !, Können Sie auch den Sicherheitsaspekt der Verwendung Ihres Ansatzes kommentieren (die Sie in der Antwort gegeben haben)? Und ob es irgendwelche Todesfälle hat? Und wie ist es unsicher/zweifelhaft, wenn ich eine System.Address als ** in ** -Parameter in der Funktion nehme und eine ** ungeprüfte Umwandlung ** in den Zugriff von ** Edit_Result_Rec_Type ** führe, weil ich diesen Ansatz auch ausprobiert habe und es hat funktioniert! –