Az Interface Definition Language, röviden IDL, olyan számítógépes nyelv, amely egy szoftverkomponens interfészét írja le. Az IDL nyelvfüggetlen módon határozza meg az interfészt, ezért lehetővé teszi az eltérő programozási nyelveken készült szoftverkomponensek együttműködését, például a C++-ban és Java-ban írt komponensek kommunikációját.
Az IDL-t leggyakrabban távoli eljáráshívási rendszerekben használják, ahol a kapcsolat két végén különböző operációs rendszerek és programozási nyelvek működhetnek. Ilyen esetben az IDL hidat képez a két eltérő rendszer között, egységesen rögzítve az elérhető műveleteket, a paramétereket, a visszatérési értékeket és az adatok továbbításának irányát.
Mi az IDL alapvető feladata?
Az IDL nem egy alkalmazáslogikát megvalósító programozási nyelv, hanem kizárólag interfészek meghatározására szolgáló nyelv. Az interfész azt írja le, hogyan kommunikálhat egy kliens egy komponenssel, miközben nem határozza meg, hogy a komponens belsőleg hogyan valósítja meg az adott műveleteket.
Az IDL használata megszünteti azt a zavart, amely akkor keletkezne, ha ugyanazt az interfészt minden programozási nyelven külön, egymástól függetlenül kellene definiálni. Az egyetlen, szabványos interfészleírás biztosítja, hogy ugyanaz az interfész több nyelven is következetesen jelenjen meg.
Az IDL-ben meghatározott interfész implementációját tetszőleges programozási nyelven meg lehet írni. A fejlesztő először az interfész szerződését rögzíti, majd az adott környezethez tartozó eszköz az IDL-leírásból nyelvspecifikus állományokat vagy kötéseket állít elő.
Miért fontos a nyelvfüggetlenség?
Egy nyelvfüggetlen architektúrában ugyanazt az interfészt nem célszerű külön-külön C++, Java és Visual Basic kóddal definiálni. Ugyanannak az interfésznek több, egymástól eltérő, de elvileg helyes definíciója alakulhatna ki, ami következetlenséghez és kompatibilitási problémákhoz vezetne.
Az IDL erre a problémára ad választ: az interfész egyetlen, nyelvfüggetlen leírásban szerepel, amelyből a különböző programozási nyelvekhez szükséges definíciók előállíthatók. Így a kliens- és szerveroldal ugyanahhoz az interfészszerződéshez igazodik.
Az IDL-t eredetileg az Open Software Foundation fejlesztette ki a Distributed Computing Environment Remote Procedure Call csomagjához. Az IDL segíti az RPC-fejlesztőket abban, hogy egy projekt kliens- és szerveroldala ugyanazt az interfészt kövesse.
Hogyan működik az IDL távoli kommunikációban?
Az IDL különösen hasznos akkor, amikor a kommunikáló szoftverkomponensek nem ugyanazon a gépen futnak, vagy nem ugyanazt a programozási nyelvet és operációs rendszert használják. A leírás meghatározza a kommunikációs szerződést, a futtatókörnyezet pedig ennek alapján gondoskodik az adatok továbbításáról.
Az interfész definíciója rögzíti, hogy milyen műveletek hívhatók meg, milyen típusú paramétereket fogadnak, milyen értéket adnak vissza, és mely paraméterek haladnak a kliens, illetve a komponens irányába. Ez az információ szükséges a távoli hívás előkészítéséhez és feldolgozásához.
A távoli eljáráshívásban részt vevő gépek eltérő operációs rendszereket és programozási nyelveket használhatnak. Az IDL ilyenkor közös szerződésként és közvetítő rétegként működik a két rendszer között.
Az IDL és a generált kód kapcsolata
Miután egy interfészt IDL-ben definiáltak, az IDL-fordító a leírást többféle forrásfájllá vagy nyelvspecifikus kötésé alakíthatja. A Microsoft IDL, vagyis a MIDL-fordító például az interfészt C és C++ nyelvű forrásállományokká fordítja.
A generált fejlécfájl tartalmazza az IDL-ben definiált interfész C++-változatát. Ez a kód hasonlít egy hagyományos C++ interfészdefinícióra, de a MIDL_INTERFACE makrót használja a class kulcsszó helyett, és hozzáadja a STDMETHODCALLTYPE makrót.
A MIDL_INTERFACE makró egy olyan struktúrát határoz meg, amelyhez UUID és novtable attribútum kapcsolódik. C++-ban a struct alapértelmezés szerint nyilvános tagokat tartalmazó osztálynak felel meg.
A __declspec(uuid(...)) Microsoft-féle C++-kiterjesztés lehetővé teszi, hogy egy GUID közvetlenül egy osztályhoz vagy struktúrához legyen rendelve. Ez az azonosító később a __uuidof(x) kiterjesztéssel lekérdezhető.
A __declspec(novtable) attribútum megakadályozza, hogy a fordító kódot generáljon az absztrakt osztály konstruktorában és destruktorában található virtuális függvénymutató inicializálásához. Ez csökkenti a kód méretét, ezért ezt az opciót absztrakt alaposztályok, például interfészdefiníciók esetén célszerű alkalmazni.
Egységes interfész különböző programozási nyelvekhez
Egy COM+ komponens bármilyen nyelven megírható, majd más nyelven készült komponensből is meghívható. Ugyanaz az ISum interfész C++-ban, Java-ban és Visual Basicben eltérő szintaktikával jelenhet meg.
Java-ban az ISum interfész a következő formában jelenik meg:
public interface ISum extends com.ms.com.IUnknown { public abstract int Sum(int x, int y); }
Visual Basicben az ISum interfész a következő formában jelenik meg:
VERSION 1.0 CLASS BEGIN MultiUse = -1 'True END Attribute VB_Name = "ISum Attribute VB_Exposed = True Attribute VB_Creatable = True Public Function Sum(x As Long, y As Long) As Long End Function
Ezek a nyelvspecifikus definíciók jól mutatják, miért van szükség közös interfészleírásra. Ha minden programozási nyelvben külön kellene meghatározni ugyanazt az interfészt, egyetlen interfésznek több, egymástól eltérő definíciója lehetne.
Az IDL fő előnyei
- Nyelvfüggetlenség: az interfész nem kötődik egyetlen programozási nyelvhez.
- Interoperabilitás: különböző nyelveken és operációs rendszereken futó komponensek kommunikálhatnak egymással.
- Közös szerződés: a kliens és a szerver ugyanazt az interfészleírást követi.
- Kódgenerálás: a leírásból nyelvspecifikus fejlécfájlok, proxyk, stubok vagy más kötési rétegek készíthetők.
- Távoli hívások támogatása: az IDL meghatározza a távoli eljáráshíváshoz szükséges paraméter- és adatátviteli információkat.
- Az interfész és a megvalósítás szétválasztása: az interfész leírása független marad a komponens belső működésétől.
- Bővíthetőség: új programozási nyelvekhez és futtatókörnyezetekhez új leképezések készíthetők.
Az interfész azonosítása UUID-val
Az IDL-ben egy interfészhez gyakran UUID, vagyis univerzálisan egyedi azonosító tartozik. A UUID egy 128 bites szám, amelyet általában hexadecimális formában ábrázolnak, és amelyet úgy terveztek, hogy térben és időben egyedi legyen.
Két különböző fejlesztő ugyanazt az ISum nevet adhatja egy interfésznek, de ha a két interfész UUID-ja eltérő, nem keletkezik azonosítási konfliktus. Az interfész neve ezért nem elegendő az egyértelmű azonosításhoz.
Az ISum interfész IDL-ben például a következőképpen definiálható:
import "unknwn.idl";
[ object, uuid(10000001-0000-0000-0000-000000000001) ] interface ISum : IUnknown { HRESULT Sum([in] int x, [in] int y, [out, retval] int* retval); };
Az object attribútum Microsoft-féle IDL-kiterjesztés, amely COM+ interfészt jelöl. Az object attribútummal nem kezdődő interfészdefiníció RPC-interfészt ír le, nem COM+ interfészt.
Paraméterirányok az IDL-ben
Az IDL-ben az interfész paramétereihez irányattribútumok rendelhetők. Az [in] attribútum azt jelzi, hogy a paramétert a kliensnek a komponens felé kell továbbítania, az [out] attribútum pedig azt, hogy a paraméter értéke a komponens felől kerül vissza a klienshez.
Az irányattribútumok azért fontosak, mert az interfész leírhatja a kliens és a komponens közötti kommunikációt akkor is, ha azok külön gépeken futnak. Az attribútumok csökkenthetik az átvitt adatok mennyiségét.
Az ISum példájában a Sum művelet első két paramétere [in] attribútumot kap. Ezeket csak a komponenshez kell továbbítani, mert az értékük nem változik meg a művelet végrehajtása során.
A harmadik paraméter [out, retval] attribútumot kap. Ez azt jelzi, hogy visszatérési értékről van szó, amelyet csak a komponenstől kell visszaküldeni a klienshez.
Az [in] attribútum nem kötelező, mivel akkor is alapértelmezett, ha nincs megadva irányattribútum.
Az IUnknown és az interfészöröklés
Az ISum interfész az IUnknown interfészből származik, amely a COM+ objektumok gyökérinterfésze. Az IUnknown definíciója az unknwn.idl fájlból importálható.
[ local, object, uuid(00000000-0000-0000-C000-000000000046), pointer_default(unique) ] interface IUnknown { typedef [unique] IUnknown *LPUNKNOWN; HRESULT QueryInterface( [in] REFIID riid, [out, iid_is(riid)] void** ppvObject); ULONG AddRef(); ULONG Release(); }
Az IDL támogatja az interfészek egyszeres öröklését a C++-hoz hasonló jelöléssel. Az öröklött interfész metódusai az új interfész metódusai előtt jelennek meg.
[object, uuid(b5483f00-4f6c-101b-a1c7-00aa00389acb)] interface IBar : IWazoo { HRESULT Bar([in] short i, [in] IFoo * pIF); };
Az interfészöröklés lehetővé teszi, hogy egy új interfész egy korábbi interfész műveleteire épüljön, miközben további műveleteket is definiálhat.
Objektuminterfészek és típusok
Az object attribútummal megjelölt interfész neve típusként is használható, és metódusparaméterként adható át.
[object, uuid(b5483f00-4f6c-101b-a1c7-00aa00389acb)] interface IFoo { };
Ezáltal létrejön egy IFoo nevű típus, amely egy másik interfész metódusában paraméterként használható.
[object, uuid(6A874340-57EB-11ce-A964-00AA006C3706)] interface IBar { HRESULT M1([in] short i, [in] IFoo* pfoo); };
Az interfész típusként való használata különösen fontos objektumalapú RPC-rendszerekben, ahol egy komponens egy másik objektumhoz tartozó interfészmutatót is átadhat.
Metódushívás C++-ban és C-ben
Objektuminterfészek metódusaiban nincs szükség handle_t paraméterre, és annak hiánya nem jelent automatikus kötést. C++-ban egy this mutató jelöli a hivatkozott távoli objektumot, C-ben pedig implicit első argumentum használható.
[object, uuid(b5483f00-4f6c-101b-a1c7-00aa00389acb)] interface IBar { HRESULT Bar([in] short i, [in] IFoo * pIF); };
C++-ban a metódus a következő módon hívható meg:
IFoo * pIF; IBar * pIB; pIB->Bar(3, pIF);
C-ben ennek megfelelő hívás a következő:
pIB->lpVtbl->Bar(pIB, 3, pIF);
Ez a mechanizmus lehetővé teszi, hogy ugyanaz az objektuminterfész eltérő nyelvi kötéseken keresztül is elérhető legyen.
Interfészmutatók és futásidőben ismert típusok
Az IDL engedélyezi a void* mutatók használatát, ha az ilyen mutatókat iid_is mutatóattribútummal minősítik. Az iid_is konstrukció azt jelzi, hogy a void* paraméter valójában interfészmutató, amelynek konkrét típusa csak futásidőben ismert.
Az interfészazonosítót az iid_is attribútumban megnevezett paraméter tartalmazza. Ez teszi lehetővé, hogy a fogadó oldal a futásidőben kapott interfészazonosító alapján értelmezze az átadott mutatót.
[object, uuid(b5483f00-4f6c-101b-a1c7-00aa00389acb)] interface IBar : IWazoo { Bar([in] short i, [in, ref] uuid_t *piid, [out, iid_is(piid)] void ** ppvoid); };
C++-ban ez a metódus például így hívható:
IFoo* pIF; pIB->Bar(i, &IID_IFoo, (void*)&pIF);
Az IID_IFoo egy olyan konstans neve, amely az IFoo interfészazonosítójának értékét tartalmazza.
Visszatérési értékek
Az IDL-ben az aszinkron metódusoknak void típust kell visszaadniuk, és csak az aszinkron metódusok térhetnek vissza void értékkel. Minden más metódusnak HRESULT értéket kell visszaadnia.
A HRESULT visszatérési típus lehetővé teszi a művelet sikerességének vagy hibájának egységes jelzését. Egyes nyelvek, például a Visual Basic és a Java, elrejtik a fejlesztő elől a visszaadott HRESULT értéket, és az [out, retval] paramétert a függvény visszatérési értékeként jelenítik meg.
Adatok leképezése és marshaling
Távoli kommunikációban a lokális adatstruktúrákat át kell alakítani olyan reprezentációvá, amely a kommunikációs csatornán továbbítható. Ezt a folyamatot marshalingnak nevezik, a fogadó oldalon pedig az adatok visszaalakítása történik.
Az IDL típusattribútumai lehetővé teszik az olyan típusok leírását, amelyek lokális reprezentációja eltér a továbbított reprezentációtól. A wire_marshal attribútum például meghatározza a felhasználói típus vezetékes, vagyis továbbítható reprezentációját.
typedef [wire_marshal( transmissible_type)] type_specifier user_type;
A user-specifikus típushoz tartozik egy transmissible type, amely megadja a hálózaton használt reprezentációt. A felhasználó a saját típusát viszonylag szabadon meghatározhatja, egyszerű, mutató- és összetett típusokat is használhat, de bizonyos korlátozásokat be kell tartani.
A legfontosabb követelmény, hogy a típusobjektum memóriamérete jól meghatározott, rögzített legyen. Ha változó méretet kell kezelni, a típusnak konformáns tömb helyett mutatómezőt kell tartalmaznia, vagy magának az érdekes típusnak a mutatójává kell válnia.
A wire_marshal attribútum nem használható együtt az allocate attribútummal, közvetlenül vagy közvetve, mivel a motor nem irányítja a típus memóriakiosztását. A vezetékes típus nem lehet interfészmutató, mivel az ilyen mutatók közvetlenül is marshalingolhatók, és nem lehet teljes mutató sem, mert az aliasolás kezelése nem biztosítható.
- A vezetékes típus nem lehet interfészmutató.
- A vezetékes típus nem lehet teljes mutató.
- A vezetékes típus nem tartalmazhat allocate attribútumot, például [allocate(all_nodes)] attribútumot.
- A vezetékes típusnak jól meghatározott memóriamérettel kell rendelkeznie.
- A vezetékes típus nem lehet konformáns szerkezet.
- A wire_marshal kölcsönösen kizárja a user_marshal, transmit_as és represent_as attribútumokat, ha ugyanarra a típusra alkalmazzák őket.
- Két különböző felhasználói típus nem oldódhat fel ugyanarra a vezetékes típusra, és fordítva.
- A felhasználói típus lehet RPC-képes, de nem kötelező annak lennie.
- A felhasználói típust ismernie kell a MIDL-nek.
A user_marshal attribútum
A user_marshal attribútum az ACF-fájlban használható, és hasonló a represent_as attribútumhoz. Minden felhasználói típushoz egy transmissible type tartozik, amely meghatározza a vezetékes reprezentációt.
typedef [user_marshal( user_type)] transmissible_type;
A generált fájlokban a transmissible_type név minden előfordulása a user_type névvel helyettesítődik. A felhasználó a saját típusát egyszerű, mutató- vagy összetett típusként határozhatja meg, de a típus memóriaméretének ebben az esetben is jól meghatározottnak kell lennie.
A user_marshal attribútum sem használható együtt az allocate attribútummal, közvetlenül vagy közvetve. A vezetékes típus nem lehet interfészmutató, teljes mutató vagy allocate attribútummal rendelkező típus.
A vezetékes típusnak rögzített memóriamérettel kell rendelkeznie, és nem lehet konformáns szerkezet. A user_marshal kölcsönösen kizárja a wire_marshal, transmit_as és represent_as attribútumokat, ha ugyanarra a típusra alkalmazzák őket.
Két különböző vezetékes típus nem oldódhat fel ugyanarra a felhasználói típusra, és fordítva. A felhasználói típus lehet RPC-képes vagy nem RPC-képes, továbbá a MIDL ismerheti vagy nem ismerheti.
Felhasználó által biztosított marshaling-rutinok
A user_marshal attribútumhoz felhasználó által megadott rutinok tartoznak. Ezek a rutinok meghatározzák az adat méretének kiszámítását, a marshalingot, az unmarshalingot és a memória felszabadítását.
unsigned long __RPC_USER <type_name>_UserSize( unsigned long __RPC_FAR * pFlags, unsigned long StartingSize, <type_name> __RPC_FAR * pFoo);
unsigned char __RPC_FAR * __RPC_USER <type_name>_UserMarshal( unsigned long __RPC_FAR * pFlags, unsigned char __RPC_FAR * Buffer, <type_name> __RPC_FAR * pFoo);
unsigned char __RPC_FAR * __RPC_USER <type_name>_UserUnmarshal( unsigned long __RPC_FAR * pFlags, unsigned char __RPC_FAR * Buffer, <type_name> __RPC_FAR * pFoo);
void __RPC_USER <type_name>_UserFree( unsigned long __RPC_FAR * pFlags, <type_name> __RPC_FAR * pFoo );
A pFlags egy jelzőértékre mutató mutató, a pBuffer az aktuális puffermutató, a pFoo pedig a felhasználói típus objektumára mutató mutató. A StartingSize az objektum előtti aktuális puffereltolást jelöli.
Méretezés, marshaling vagy unmarshaling esetén a visszatérési érték az új eltolás vagy pufferpozíció. A jelzők tartalmazhatják a lokális hívás jelzőjét és az adatábrázolás jelzőjét.
| Jelző | Jelentés |
|---|---|
| MSHCTX_LOCAL | 0 |
| MSHCTX_NOSHAREDMEM | 1 |
| MSHCTX_DIFFERENTMACHINE | 2 |
| MSHCTX_INPROC | 3 |
A jelzők lehetővé teszik, hogy a rutinok a RPC-hívás környezetétől függően eltérően működjenek. Egy folyamaton belül továbbított fogantyú például fogantyúként, egy távoli gépre küldve pedig a fogantyúhoz kapcsolódó adatokként továbbítható.
A UserSize rutin feladata
A *_UserSize rutin akkor hívódik meg, amikor az RPC-adatpuffer méretét meg kell határozni a kliens- vagy szerveroldali marshaling előtt. A rutinnak kumulatív mérettel kell dolgoznia.
A StartingSize argumentum az aktuális puffereltolás. A rutinnak olyan kumulatív méretet kell visszaadnia, amely tartalmazza az esetleges kitöltést, majd az adat méretét.
A kezdőméret a felhasználói objektum pufferbeli eltolását jelzi, és nem feltétlenül megfelelően igazított. A felhasználói rutinnak ezért minden szükséges kitöltésről gondoskodnia kell.
Másképpen megfogalmazva a rutin az objektum utáni új eltolást adja vissza. A méretezési rutint nem kell meghívni, ha a vezetékes méret fordítási időben kiszámítható.
A legtöbb uniónál a vezetékes reprezentáció tényleges mérete futásidőben határozható meg akkor is, ha az unión belül nincsenek mutatók. A rutin túlbecsülheti a méretet, amennyiben a marshaling rutin nem használ többet annál, mint amit a méretezési rutin előre jelzett.
Az IDL, a COM és a rendszer szabványai
A COM-infrastruktúra teljesen elválik a COM-komponensek létrehozására és használatára szolgáló forráskód-szintű eszközöktől. A COM teljes egészében bináris specifikáció, ezért a forráskód-szintű specifikációk és szabványok nem részei a rendszer alapvető architektúrájának.
Ez magában foglalja az interfészdefiníciós nyelvek minden formáját is. Egy megfelelő IDL interoperábilis szabványának kialakítása ettől még rendkívül értékes és hasznos, de fontos megérteni, hogy ez eszközszintű szabvány, nem pedig alapvető rendszerszintű szabvány.
A COM-komponensek egyedi COM-interfészekkel IDL használata nélkül is felépíthetők. A rendszerszabványok és az eszközszabványok világos szétválasztása lehetővé teszi, hogy a COM-eszközök gyártói központi szabványügyi testülethez való igazodás nélkül is fejleszthessék eszközeiket.
A forráskód-szintű szabványok ettől még hasznosak, és a DCE IDL ilyen szabványnak tekinthető. A DCE IDL-hez hozzáadott kiterjesztések lehetővé teszik COM-interfészek meghatározását a DCE RPC-interfészek mellett.
ODL-kiterjesztések és típuskönyvtárak
Az Automation esemény- és tulajdonságkezeléséhez néhány kiterjesztést definiál a típuskönyvtár-technológia. Ezek a kiterjesztések funkcionálisan nem módosítják az Automation működését, hanem kibővítik az objektum típuskönyvtárának létrehozására használt Object Definition Language nyelvet.
Egy vezérlő típuskönyvtár segítségével írja le tulajdonságait, metódusait és eseményeit a használni kívánó tárolók számára. A hozzáadott attribútumok a következők: Bindable, RequestEdit, DefaultBind, DisplayBind, Licensed, Source, Restricted és Default.
- Bindable: az ilyen attribútummal rendelkező tulajdonság változásakor az objektum OnChanged értesítést küld.
- RequestEdit: a tulajdonság módosítása előtt az objektum RequestEdit értesítést küld, amely lehetővé teszi, hogy a tulajdonságfigyelő megszakítsa a változtatást.
- DefaultBind: adatkapcsolt vezérlők tulajdonságainak kezeléséhez kapcsolódó jellemzőt határoz meg.
- DisplayBind: adatforráshoz kötött vezérlők megjelenítési tulajdonságainak kezelését írja le.
- Licensed: a típuskönyvtár coclass-bejegyzéseihez kapcsolódó attribútum.
- Source: kimenő interfészt jelöl, amelyet az objektum másik sink objektum meghívására kíván használni.
- Restricted: elrejti az interfészt a makróprogramozási nyelvek és az általános automatizálási kliensek elől.
- Default: az alapértelmezett kimenő interfészt jelölheti.
A Source attribútummal megjelölt dispinterface-t az objektum nem maga valósítja meg, hanem olyan interfészként jelöli, amelyet egy másik sink objektumban szeretne meghívni. Ezt kimenő interfésznek nevezik.
Egy objektum több kimenő interfészt is megadhat, de ezek közül csak egyet jelölhet Default attribútummal. Az objektum típustájékoztatásában szereplő alapértelmezett Source dispinterface határozza meg az objektum eseménykészletét.
A Restricted attribútum lehetővé teszi, hogy egy vezérlő elrejtse az interfészt a makróprogramozási nyelvek elől. A korlátozott interfészeket általános automatizálási klienskód nem hívhatja meg, mert a klienseszköz nem teszi elérhetővé az interfészt a programozó számára.
Az IDL alkalmazása OpenMI-szerű rendszerekben
Egy OpenMI-szerű rendszerben az IDL egyik lehetséges felhasználása az OpenMI-szabvány interfészeinek nyelvfüggetlen formátumban történő meghatározása, majd leképezések biztosítása az OATC által támogatott nyelvekhez, például a CLS-hez és a Java-hoz.
Ez általánosabbá teheti az OpenMI-t, és megnyithatja az utat a későbbi, más programozási nyelveken készült implementációk előtt, ugyanakkor növeli a rendszer összetettségét.
Az IDL másik lehetséges felhasználása az IDL és a CLS-hez, illetve Java-hoz definiált leképezések alkalmazása a modellek közötti interoperabilitás megvalósítására. Ehhez például az IIOP.Net és a Java RMI/IIOP használható.
| Felhasználási mód | Előny | Korlát |
|---|---|---|
| Az OpenMI interfészeinek nyelvfüggetlen definiálása | Általánosabb szabvány és új nyelvek támogatásának lehetősége | Nagyobb összetettség |
| IDL-leképezések használata modellek között | Interoperabilitás eltérő nyelveken készült modellek között | Kommunikációs és leképezési infrastruktúra szükséges |
Mikor érdemes IDL-t használni?
IDL-t akkor érdemes használni, ha egy interfészt több programozási nyelven vagy több platformon kell elérhetővé tenni. Különösen hasznos olyan rendszerekben, amelyekben a kliens és a szolgáltató külön folyamatban vagy külön gépen fut.
Az IDL akkor is előnyös, ha az interfészt hosszabb időn keresztül fenn kell tartani, és fontos, hogy a különböző komponensek ugyanazt a kommunikációs szerződést kövessék. A központi interfészleírás csökkenti annak kockázatát, hogy a kliens- és szerveroldali definíciók eltérjenek.
Az IDL különösen indokolt RPC-, COM-, CORBA- és más komponensalapú rendszerekben, ahol az adatok és műveletek határokon keresztül jutnak el egyik komponensből a másikba. Az IDL segítségével ezek a határok formálisan és géppel feldolgozható módon írhatók le.
Mire nem való az IDL?
Az IDL nem helyettesíti az alkalmazáslogikát, és nem írja le a komponens belső algoritmusait. Nem határozza meg, hogyan számolja ki a komponens az eredményt, hogyan tárolja az adatokat, vagy hogyan kezeli a belső állapotot.
Az IDL nem általános célú programozási nyelv. Az interfész műveleteit és adattípusait írja le, de a tényleges megvalósítást egy másik programozási nyelven kell elkészíteni.
Az IDL önmagában nem garantálja az interoperabilitást sem. Szükség van kompatibilis futtatókörnyezetre, fordítóra, megfelelő nyelvi leképezésekre, azonos adatábrázolási szabályokra és a kommunikációs infrastruktúra helyes működésére.
Az IDL legfontosabb gyakorlati szerepe
Az IDL legfontosabb gyakorlati szerepe az, hogy egyetlen, közös és nyelvfüggetlen szerződésben rögzíti a szoftverkomponensek közötti kommunikációt. Ez a szerződés lehetővé teszi, hogy ugyanazt a komponenst különböző nyelveken írt kliensek érjék el.
Az IDL elválasztja egymástól az interfészt és annak implementációját, egységesíti a paraméterek és visszatérési értékek kezelését, továbbá támogatja a távoli hívásokhoz szükséges típus- és adatátviteli szabályokat.
Ennek köszönhetően az IDL hidat képez a különböző programozási nyelvek, operációs rendszerek, folyamatok és gépek között, miközben az interfész definíciója egyetlen közös referencia marad.
