Ada 编程/接口
外观
< Ada 编程
Ada 是少数几种将接口作为语言标准一部分的语言之一。程序员可以与其他编程语言或硬件进行接口。
语言标准定义了与 C、Cobol 和 Fortran 的接口。当然,任何实现都可能定义进一步的接口——例如,GNAT 定义了与 C++ 的接口。
实际上,通过 pragma 导出、导入 和 约定 提供与其他语言的接口。
包 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
Mainis
procedure
W32_Open_File_Dialogis
package
Crenames
Interfaces.C;use
C;type
OPENFILENAMEis
new
System.Address;type
Window_Typeis
new
System.Address;function
GetOpenFileName (p : OPENFILENAME)return
C.int;pragma
Import (C, GetOpenFileName, "ada_getopenfilename");function
Allocatereturn
OPENFILENAMEwith
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 = 0then
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'Addressuse
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 为与硬件接口提供了广泛的支持,例如使用 表示子句 来指定硬件使用的类型的精确表示,或使用标准中断处理来编写 中断服务例程。
- 附录 B 与其他语言的接口 (注释)
- 附录 C 系统编程 (注释)