跳至内容

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 质量和风格指南

[编辑 | 编辑源代码]
华夏公益教科书