跳轉到內容

Ada 程式設計/平臺/Windows/Visual C++ - GNAT 介面

來自華夏公益教科書,自由的教科書

Ada. Time-tested, safe and secure.
Ada. 經久考驗,安全可靠。


本指南介紹了在 Windows 中使用 GNAT 和 MS Visual C++ 從 Ada 連線到 C++ 的方法。

在開始之前,您應該檢查您的環境。以下是編寫本指南時所使用的環境。

  1. Ada GPL 2006 和 GPS。
  2. Microsoft Visual Studio 2005

我們將遵循以下步驟

  1. 編寫您的 Ada 程式碼並構建動態庫
  2. 建立 .lib 檔案(用於靜態連結)
  3. 協同工作
  4. 執行您的程式碼

步驟 1. 編寫 Ada 原始碼

[編輯 | 編輯原始碼]
----------------------------- t.ads
 with interfaces.c;
 package t is
 
    package C renames interfaces.c;
 
    procedure test(a,b,z,d,e:c.int) ;
    pragma export (stdcall, test, "test");
 
 end t;
--------------------------------t.adb

 with ada.text_io;
 with t.th;
 package body t is
    procedure test(a,b,z,d,e:c.int) is
       myd : integer := 0;
    begin
       t.th.t.getToken (myd);
       ada.text_io.put_line(myd'img & " and e value is" & c.int'image(e));
    end;
 
 end t;
------------------------------------th.ads
 package t.th is
 
    task T is
       entry getToken (t : out integer);
    end;
 private
 d : integer := 0;
 
 end t.th;
-------------------------------------th.adb

 with ada.text_io;
 package body t.th is
    task body T is
       use ada.text_io;
 
    begin
 
       loop
          select
             accept getToken (t : out integer) do
                t := d;
             end getToken;
          or
             terminate;
          end select;
          d := d + 1;
       end loop;
 
    end ;
 end t.th;

最重要的是您的專案檔案。它讓您更容易。

project Testdll is
   for Library_Name use "Te";
   for Library_Dir use "dll";
   for Library_Ali_Dir use "ali";
   for Library_Kind use "dynamic";
   for Languages use ("Ada");
   for Object_Dir use "obj";
   for Library_Interface use ("t");

   for Library_Auto_Init use "False";
   for Library_Src_Dir use "dll";
end Testdll;

您可以在 GPS IDE 中配置幾乎所有設定。但請注意,GPS 無法正確進行 Library_Interface 設定。配置完成後,您應該檢查專案檔案並相應地修改它。Library_Interface 指的是 DLL 中包含匯出函式的包。

Library_Auto_Init 很有趣,您必須在專案中選擇一個正確的設定。

如果選擇 True,則庫載入時將呼叫 adaInit(這意味著細化會在載入時間自動出現);如果選擇 False,則會在 DLL 中匯出 init 和 finalize 函式,您必須自己呼叫它們。

如果您匯出像 C/C++ "普通" 函式一樣的函式,沒有任何細化部分,則可以將 library_auto_init 設定為 True。

如果您的 Ada 程式碼不僅僅像 C/C++ 一樣工作,而且還需要 Ada 細化函式,那麼您應該自己進行初始化/結束處理。

"危險" 危險" 危險" 危險" 危險"

例如,如果您有一個庫級任務需要在載入時間進行細化,並且使用隱式連結並載入它,那麼當 DllMain 呼叫 init 程式碼時,它將 "死鎖等待"。這是一種您不希望出現的意外行為。

危險" 危險" 危險" 危險" 危險"

在某些情況下,您可以使用 LoadLibrary / GetProcAddress 來工作(顯式載入)。但這並不容易管理您的程式碼,尤其是在匯出許多函式的情況下。

步驟 2. 建立 .lib 檔案(用於靜態連結)

[編輯 | 編輯原始碼]

您可以使用實用程式 dumpbin 和 lib 來生成 .lib 檔案(2.A)

    dumpbin/exports Te.dll > te.def,

檔案內容是

Microsoft (R) COFF/PE Dumper Version 8.00.50727.42
Copyright (C) Microsoft Corporation.  All rights reserved.

檔案 te.dll 的轉儲

File Type: DLL
 Section contains the following exports for Te.dll
   00000000 characteristics
   44E2ABD2 time date stamp Wed Aug 16 13:23:30 2006
       0.00 version
          1 ordinal base
         19 number of functions
         19 number of names

   ordinal hint RVA      name

         1    0 00001461 Tefinal
         2    1 000011A0 Teinit
         3    2 00005130 _CRT_MT
         4    3 000050E0 t_E
         5    4 000050D0 t__th_E
         6    5 0000155F t__th__P2sIP
         7    6 00007040 t__th___chain
         8    7 00001745 t__th___elabb
         9    8 0000156E t__th___elabs
        10    9 00007044 t__th___master
        11    A 000050D8 t__th__d
        12    B 00007048 t__th__t
        13    C 00006010 t__th__tT1
        14    D 000016B9 t__th__tTKB
        15    E 000050D1 t__th__tTKE
        16    F 00001490 t__th__tTKVIP
        17   10 000050D4 t__th__tTKZ
        18   11 00005000 temain_E
        19   12 0000178F test@20

 Summary

       1000 .bss
       1000 .data
       1000 .edata
       2000 .idata
       1000 .rdata
       1000 .reloc
      2E000 .stab
      E3000 .stabstr
       4000 .text

(2.b) 刪除 Te.def 中的所有內容,但保留...

EXPORTS
         Tefinal
         Teinit
         _CRT_MT
         t_E
         t___elabb
         t__th_E
         t__th__P2sIP
         t__th___elabb
         t__th__d
         t__th__tB
         t__th__tE
         t__th__tVIP
         t__th__tZ
         temain_E
         test@20

Teinit 和 Tefinal 用於在 Te.dll 載入後細化和終止 Ada 細化部分。(名稱不叫 adainit/adafinalize,但仍然是 adainit/adafinalize 的相同函式)

步驟 3. 在 MS VC++ 中協同工作

[編輯 | 編輯原始碼]

啟動 Visual Studio C++ 專案,並將 Te.lib 新增到連結器設定中。

編寫一個 Te.h 標頭檔案用於 Ada DLL(GPS 應該為您生成 .lib 和 .h)。

extern "C" extern void _stdcall test(int a,int b,int c,int d,int e);
extern "C" extern void  Teinit();
extern "C" extern void  Tefinal();

並編寫一個 C/C++ 測試程式碼來生成一個 .exe 檔案。

#include "stdafx.h" //visual c++ default header
#include "Te.h" //your ada library header
 
int _tmain(int argc, _TCHAR* argv[])
{
 
  Teinit();  //start init
  for (int i = 0 ; i< 300 ;i++)
     test(0,0,0,0,i);
 
  Tefinal(); //end  init
  return 0;
 
}

步驟 4. 執行您的程式碼

[編輯 | 編輯原始碼]

將 .exe 和 .dll 放置在同一個目錄中並執行測試。

載入程式將按照以下順序查詢 dll:

  1. 當前目錄
  2. path 變數
  3. Windows 目錄

將 dll 和 exe 放置在同一個目錄中,這是最好的選擇。

華夏公益教科書