跳至內容

Ada 程式設計/介面

來自華夏公益教科書

Ada. Time-tested, safe and secure.
Ada。經久耐用、安全可靠。

Ada 是少數幾種將介面作為語言標準一部分的語言之一。程式設計師可以與其他程式語言或硬體進行介面。

其他程式語言

[編輯 | 編輯原始碼]

語言標準定義了與 CCobolFortran 的介面。當然,任何實現都可能定義進一步的介面——例如,GNAT 定義了與 C++ 的介面。

實際上,透過 pragma 匯出匯入約定 提供與其他語言的介面。

與 C 介面

[編輯 | 編輯原始碼]

包 Interfaces.C 用於定義 C 型別。C 函式包裝器應用於封裝 C 端的型別和函式。這樣,程式碼就是可移植的,並且可以向前相容。這類似於 Java 的 JNI 中與 C 互動的方式。包裝器應用於

  • 將 C include 中定義的 typedef 轉換為 Interfaces.C 中定義的型別;
  • 使用宏並將宏值暴露給 Ada 端;
  • 使用可變引數列表函式;
  • 為接受弱型別引數的函式定義多個函式包裝器,例如接受 char_array 或空指標的函式;
  • 為依賴於作業系統版本或其他編譯時方面的 C 結構體使用 getter 和 setter;
  • 使用指標運算;
  • 使 Ada 原始碼保持記憶體安全。
with Interfaces.C;
with System;
with Ada.Text_IO;

procedure Main is
   procedure W32_Open_File_Dialog
   is
      package C renames Interfaces.C;
      use C;
      
      type OPENFILENAME is new System.Address;
      type Window_Type is new System.Address;
      
      function GetOpenFileName (p : OPENFILENAME) return C.int;
      pragma Import (C, GetOpenFileName, "ada_getopenfilename");
      
      function Allocate return OPENFILENAME with
        Import => True,
        Convention => C,
        External_Name => "ofn_allocate";
      
      procedure Set_Struct_Size (X : OPENFILENAME) with
        Import => True,
        Convention => C,
        External_Name => "ofn_set_struct_size";
      
      procedure Set_Owner (X : OPENFILENAME; Owner : Window_Type) with
        Import => True,
        Convention => C,
        External_Name => "ofn_set_owner";
      
      procedure Set_File (X : OPENFILENAME; File : char_array; Length : C.int) with
        Import => True,
        Convention => C,
        External_Name => "ofn_set_file";
      
      procedure Set_Filter (X : OPENFILENAME; Filter : char_array);
      pragma Import (C, Set_Filter, "ofn_set_filter");
      
      procedure Set_Filter_Index (X : OPENFILENAME; N : C.int) with
        Import => True,
        Convention => C,
        External_Name => "ofn_set_filter_index";
      
      function Get_File (X : OPENFILENAME) return System.Address;
      pragma Import (C, Get_File, "ofn_get_file");
      
      function Get_File_Length (X : OPENFILENAME) return C.size_t;
      pragma Import (C, Get_File_Length, "ofn_get_file_length");
      
      procedure Free (X : OPENFILENAME) with
        Import => True,
        Convention => C,
        External_Name => "ofn_free";
      
      OFN : OPENFILENAME;
      Ret : C.int;
      File : aliased C.char_array := "test.txt" & C.nul;
      Filter : aliased C.char_array := "All" & C.nul & "*.*" & C.nul & C.nul & C.nul;
   begin
      OFN := Allocate;
      Set_Struct_Size (OFN);
      Set_Owner (OFN, Window_Type (System.Null_Address));
      Set_File (OFN, File, 256);
      Set_Filter (OFN, Filter);
      Set_Filter_Index (OFN, 0);
      Ret := GetOpenFileName (OFN);
      if Ret = 0 then
         Free (OFN);
         Ada.Text_IO.Put_Line ("No file selected.");
         return;
      end if;
      declare
         Selected_File_Address : System.Address := Get_File (OFN);
         Selected_File_Length : C.size_t := Get_File_Length (OFN);
         Selected_File : char_array (1 .. Selected_File_Length + 1);
         for Selected_File'Address use Selected_File_Address;
      begin
         Ada.Text_IO.Put_Line (To_Ada (Selected_File, Trim_Nul => True));
      end;
      Free (OFN);
   end W32_Open_File_Dialog;
begin
   W32_Open_File_Dialog;
end Main;



#include <windows.h>
#include <stdlib.h>

OPENFILENAME *ofn_allocate()
{
    OPENFILENAME *ofn;
    ofn = (OPENFILENAME *) malloc(sizeof(OPENFILENAME));
    if (ofn == NULL)
        return NULL;
    memset(ofn, 0, sizeof(OPENFILENAME));
    return ofn;
}

void ofn_set_struct_size(OPENFILENAME *ofn)
{
    ofn->lStructSize = sizeof(OPENFILENAME);
}

void ofn_set_owner(OPENFILENAME *ofn, void *owner)
{
    ofn->hwndOwner = (HWND) owner;
}

void ofn_set_file(OPENFILENAME *ofn, char *file, int length)
{
    if (ofn->lpstrFile)
        free(ofn->lpstrFile);
    ofn->lpstrFile = (char *)malloc (length);
    if (ofn->lpstrFile == NULL) {
        ofn->nMaxFile = 0;
        return;
    }
    strncpy(ofn->lpstrFile, file, length);
    ofn->nMaxFile = length;
}

void ofn_set_filter(OPENFILENAME *ofn, char *filter)
{
    ofn->lpstrFilter = filter;
}

void ofn_set_filter_index(OPENFILENAME *ofn, int n)
{
    ofn->nFilterIndex = n;
}

void ofn_free(OPENFILENAME *ofn)
{
    if (ofn->lpstrFile)
        free(ofn->lpstrFile);
    free(ofn);
}

int ada_getopenfilename(OPENFILENAME *ofn)
{
    return (int) GetOpenFileNameA(ofn);
}

char *ofn_get_file(OPENFILENAME *ofn)
{
    return ofn->lpstrFile;
}

size_t ofn_get_file_length(OPENFILENAME *ofn)
{
    return (size_t) lstrlen (ofn->lpstrFile);
}

以下專案檔案 (getopenfilename.gpr) 顯示瞭如何連結到 comdlg32.dll

project Getopenfilename is
   for Languages use ("Ada", "C");
   for Source_Dirs use ("src");
   for Object_Dir use "obj";
   for Main use ("main.adb");

   package Linker is
      for Default_Switches ("ada") use ("-lComdlg32");
   end Linker;
end Getopenfilename;

硬體裝置

[編輯 | 編輯原始碼]

嵌入式程式設計師通常需要編寫裝置驅動程式。Ada 為與硬體介面提供了廣泛的支援,例如使用 表示子句 來指定硬體使用的型別的精確表示,或使用標準中斷處理來編寫 中斷服務例程

華夏公益教科書

[編輯 | 編輯原始碼]

Ada 語言參考手冊

[編輯 | 編輯原始碼]

Ada 95 理念

[編輯 | 編輯原始碼]

Ada 質量和風格指南

[編輯 | 編輯原始碼]
華夏公益教科書