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 系統程式設計 (註釋)
