5

int func( int a, int* b)Ada 95 でインポートして使用する必要がある C 関数があります。通常、C 関数は C で次のように呼び出されます。c = func(a, &b);

私は常に C 関数を Ada にインポートしていますが、参照渡しの引数を持つ関数を使用することは常に避けてきましたが、ついに学ぶ時が来ました。

Ada でこの関数を宣言する方法を知りたいです。また、示されている宣言された変数でそれを使用する簡単な例も知りたいです (私はまだアクセス型について少し曖昧であるため)。

皆さんありがとう!

4

2 に答える 2

9

C ではint* b、多くのことを意味します。おそらく、それは実際には 1 つの変数へのポインターに過ぎませんint aが、長さの配列である可能性もあります。このコードは、int* b実際には参照によって渡される単なる値であると想定しています。

with Interfaces.C;

-- ...
package C renames Interfaces.C;

function Func (A : C.int; B : access C.int) return C.int;
pragma Import (Convention => C, Entity => Func,
               External_Name => "func");

-- ...

declare
   A : C.int := 42;
   B : aliased C.int := 23;
   C : C.int;
begin
   C := Func (A, B'Access);
   -- ...
end;

'Access変数で使用できaliasedます。これは、ポインターが C 側に格納されず、 variable の有効期間が終了した後にアクセスされないことが確実である限り、安全ですB。(C 宣言でconstキーワードを使用する場合access constant、Ada 側で使用できますが、それは Ada 2005 のみです。)

名前付きタイプを使用することもできます。

-- ...
type Int_Access is access C.int;
function Func (A : C.int; B : Int_Access) return C.int;
-- ...
C := Func (A, B'Unchecked_Access);
-- ...

Ada は通常、非ローカル アクセス タイプ (as ) がローカル変数を参照することを'Unchecked_Access許可しないため、使用する必要があります。Int_AccessC コードがポインターに対して何をするかがわかっている場合 (当然のように)、名前付き型を使用して、ローカル変数への参照を渡さないように指定できます。

注 1:プロシージャ (C では を返す関数) がある場合、Ada プロシージャ宣言で の代わりに をvoid使用して、参照渡しされる変数を指定できます。このように、アクセス タイプについてまったく心配する必要はありません。前と同様に、ポインターが C 側に格納されていないことを確認する必要があります。in outaccess

注意 2:レコード型と配列は、指定しない限り、とにかく参照によって渡されますpragma Convention (C_Pass_By_Copy, Your_Type);。これは、Ada で C 関数をラップするときによくある落とし穴です。

于 2012-06-25T14:22:16.723 に答える
4

(および flyx からの盗作) に加えて、完全な解決策を提供します。

ファイル c_thing.c

#include <stdio.h>

int foo (int a, int * b) {
  printf ("A:%d, B %d\n",a, *b);
}

ファイル ada_main.adb

with Interfaces.C;

procedure Ada_Main is 

   package C renames Interfaces.C;

   function Func (A : C.int; B : access C.int) return C.int;
   pragma Import (Convention => C, Entity => Func,
                  External_Name => "foo");

   A : C.int := 42;
   B : aliased C.int := 23;
   R : C.int;

begin

   R := Func (A, B'Access);

end Ada_Main;

コンパイルするには (Linux):

gcc -c c_thing.c
gnatmake -c ada_main.adb
gnatbind ada_main.ali
gnatlink ada_main.ali c_thing.o

走る

./ada_main 
A:42, B 23
于 2012-06-25T20:40:54.923 に答える