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 源代码保持内存安全。
withInterfaces.C;withSystem;withAda.Text_IO;procedureMainisprocedureW32_Open_File_DialogispackageCrenamesInterfaces.C;useC;typeOPENFILENAMEisnewSystem.Address;typeWindow_TypeisnewSystem.Address;functionGetOpenFileName (p : OPENFILENAME)returnC.int;pragmaImport (C, GetOpenFileName, "ada_getopenfilename");functionAllocatereturnOPENFILENAMEwithImport => True, Convention => C, External_Name => "ofn_allocate";procedureSet_Struct_Size (X : OPENFILENAME)withImport => True, Convention => C, External_Name => "ofn_set_struct_size";procedureSet_Owner (X : OPENFILENAME; Owner : Window_Type)withImport => True, Convention => C, External_Name => "ofn_set_owner";procedureSet_File (X : OPENFILENAME; File : char_array; Length : C.int)withImport => True, Convention => C, External_Name => "ofn_set_file";procedureSet_Filter (X : OPENFILENAME; Filter : char_array);pragmaImport (C, Set_Filter, "ofn_set_filter");procedureSet_Filter_Index (X : OPENFILENAME; N : C.int)withImport => True, Convention => C, External_Name => "ofn_set_filter_index";functionGet_File (X : OPENFILENAME)returnSystem.Address;pragmaImport (C, Get_File, "ofn_get_file");functionGet_File_Length (X : OPENFILENAME)returnC.size_t;pragmaImport (C, Get_File_Length, "ofn_get_file_length");procedureFree (X : OPENFILENAME)withImport => True, Convention => C, External_Name => "ofn_free"; OFN : OPENFILENAME; Ret : C.int; File :aliasedC.char_array := "test.txt" & C.nul; Filter :aliasedC.char_array := "All" & C.nul & "*.*" & C.nul & C.nul & C.nul;beginOFN := 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);ifRet = 0thenFree (OFN); Ada.Text_IO.Put_Line ("No file selected."); return;endif;declareSelected_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);forSelected_File'AddressuseSelected_File_Address;beginAda.Text_IO.Put_Line (To_Ada (Selected_File, Trim_Nul => True));end; Free (OFN);endW32_Open_File_Dialog;beginW32_Open_File_Dialog;endMain;
#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 系统编程 (注释)
