2014-04-01 54 views
1

我想從ADA程序將記錄數組傳遞給C程序。 C代碼如下所示:將記錄數組傳遞給ADA中的C程序

dongo.h

typedef struct _RFC_CONNECTION_PARAMETER 
{ 
    const char * name; 
    const char * value; 
} RFC_CONNECTION_PARAMETER; 

void open(RFC_CONNECTION_PARAMETER const * connectionParams, int n); 

dongo.c:

#include "dongo.h" 
#include <stdio.h> 

void open(RFC_CONNECTION_PARAMETER const * connectionParams, int n) 
{ 
    int i; 
    printf("Hello\n"); 
    for(i=0; i<n; i++) 
    { 
     printf("%d : %s = %s\n", i,connectionParams[i].name,connectionParams[i].value);  
    } 
} 

的ADA-代碼是:

with dongo_h; use dongo_h; 
with Interfaces.C; use Interfaces.C; 

with System; 

procedure main is 
    type RFC_CONNECTION_PARAMETER_PTR is access all RFC_CONNECTION_PARAMETER; 

    type RFC_CONNECTION_PARAMETER_ARRAY  is array (Interfaces.C.int range <>) of RFC_CONNECTION_PARAMETER_PTR; 
    pragma Convention (C, RFC_CONNECTION_PARAMETER_ARRAY); 
    par : RFC_CONNECTION_PARAMETER_ARRAY(1..2); 
    begin 
     par(1) := new RFC_CONNECTION_PARAMETER; 
     par(2) := new RFC_CONNECTION_PARAMETER; 
     par(1).name  := New_String("ABC"); 
     par(1).value  := New_String("123"); 
     par(2).name  := New_String("ABC"); 
     par(2).value  := New_String("456"); 
     open(par'Address,2); 
end; 

的makefile中Mingw64-Toolchain是:

main.exe : main.adb dongo.h dongo.c 
    gcc -fdump-ada-spec dongo.h 
    gcc -c -m64 dongo.c 
    gnatmake -c main.adb 
    gnatbind -x main.ali 
    gnatlink -M -v main.ali -lmingw32 dongo.o -o main.exe 

程序gnerates怪異隨機輸出,有什麼指示參數傳遞是不工作的。在互聯網上找不到完整的例子之後,我在這裏發佈這個問題,希望有人能夠向我解釋如何正確地完成參數傳遞。

在此先感謝。

多虧了有用的提示從論壇的成員,我可以告訴我的最終解決方案:

main1.adb:

with dongo_h; use dongo_h; 
with Interfaces.C; use Interfaces.C; 
with Interfaces.C.Strings; use Interfaces.C.Strings; 
with System; 

procedure main1 is 
    type RFC_CONNECTION_PARAMETER_ARRAY is array (Interfaces.C.int range <>) of RFC_CONNECTION_PARAMETER; 
    pragma Convention (C, RFC_CONNECTION_PARAMETER_ARRAY); 
    par : RFC_CONNECTION_PARAMETER_ARRAY(1..2); 

begin 
    par(1).name  := New_String("ABC"); 
    par(1).value := New_String("123"); 
    par(2).name  := New_String("ABC"); 
    par(2).value := New_String("456"); 
    open(par'address,2); 
end; 
+2

在C端的陣列是-的-結構,但在所述陣列Ada-side看起來像一個指向結構的指針數組(不確定,從未使用過Ada)。 – Dirk

+0

Dirk是正確的。 C代碼需要一個數組,其中每個數組元素是兩個「單詞」(實際上是兩個指針)。但是,Ada數組中的每個元素只有一個「單詞」(一個指針)。所以他們不會匹配。如果您需要更多幫助,請發佈RFC_CONNECTION_PARAMETER類型的Ada聲明以及其他任何涉及的用戶定義類型。另外,'New_String'是'Interfaces.C.Strings'還是你自己的? – ajb

+0

是的,謝謝你們倆。將C程序中的Mehtod簽名更改爲:void open(RFC_CONNECTION_PARAMETER const ** connectionParams,int n);'它的工作原理。 – user3485675

回答

1

到您的文章的意見是正確的,你需要有一個數組記錄並將指針傳遞給導入的函數。

with Interfaces.C.Strings; use Interfaces.C.Strings; 
procedure Main is 
    function NS renames New_String; 
    type Record_Parameter is record 
    Name : Chars_Ptr; 
    Value : Chars_Ptr; 
    end record; 
    type Array_Record_Parameter 
    is array (Int range <>) of Record_Parameter; 
    type Access_Array_Record_Parameter 
    is access all Array_Record_Parameter; 
    pragma Convention(C, Access_Array_Record_Parameter); 
    procedure Open_With(
    Parameters : in Access_Array_Record_Parameter; 
    Count  : in Int); 
    pragma Import(Stdcall, "open", Open_With); 
    Parameters : aliased Array_Record_Parameter := 
    ((NS("ABC"), NS("123")), (NS("ABC"), NS("456"))); 
    begin 
    Open_With(Parameters'access, Int(Parameters'length)); 
    end Main; 

編輯:「訪問應該被用來代替」 Unrestricted_Access和參數應已‘別名’

+0

精彩的回答。該代碼確實有效。在我的環境中,我不得不將''with' -Statement改爲'pragma Import(C,Open_With,「open」);' – user3485675

+0

爲什麼使用'Unrestricted_Access? –

+0

很顯然,'unrestricted_access'似乎充當了C中的'&'。實際上,代碼也適用於所有類型,並且簽名僅更改爲'Array_Record_Parameter'。然後,'Open_With(Parameters,int(Parameters'length))'沒有這個「cast」。 – user3485675