1. fejezet - ablakok programozása

Programozás Windows rendszerhez

Nos, a DirectX telepítve van, a fordítója be van állítva, és készen állsz! Várj csak egy kicsit, barátom, van néhány dolog, amire figyelned kell, mielőtt a szerepjátékok programozási világába sietned.

Először is, számos olyan témával foglalkozik a Windows, amelyről meg akarok beszélni. Ezek a témák magukban foglalják a szálak és multithreading, a kritikus szakaszok és a COM-k tanulmányozását. Úgy gondolom, hogy ez az információ feltétlenül szükséges a könyv hátralevő részének olvasásához (tipp, tipp).

Szálak és többszöveg

Windows 95 bevezette a programozók az ötletet, hogy multitasking rendszerek (annak ellenére, hogy a Windows nem igaz multitasking operációs rendszer, mert használ elővásárlási multitasking, amelyben apró sokaságát programok végrehajtása egyesével). Az ötlet az, hogy több folyamatban (alkalmazás) fut egyszerre, amelyek mindegyikét a processzor időtartamának (időszeletnek) nevezzük.

A többfeladatú műveletek lehetővé teszik, hogy az egyes folyamatokat több különálló alfolyamathoz kell felosztani. Mindegyik szálnak saját feladata van, például a hálózati adatok beolvasása, felhasználói beadványok feldolgozása vagy hang lejátszása. Egyetlen alkalmazásban több szálat használunk multithreadingnek.

Az alkalmazáson belül további szálak létrehozása egyszerű. Szál létrehozásához létre kell hozni egy függvényt (speciális függvény prototípus használatával), amely tartalmazza a végrehajtani kívánt kódot. A stream funkcióhoz használt prototípus így néz ki:

Az lpParameter paraméter egy olyan felhasználó által definiált mutató, amelyet megad, ha létrehoz egy folyamatot a CreateThread funkcióval:

A CreateThread funkció által visszaadott érték egy olyan leíró, amelyet le kell zárni, amikor leáll, vagy a rendszer erőforrásai nem kerülnek kiadásra. A menet által használt erőforrások felszabadulnak a CloseHandle funkció meghívásával.

Ez egy bonyolult feladat, és nem fogok beleilletni munkájának részleteibe, hanem inkább példát fogok adni, amelyet sablonként használhat. A példa egy egyszerű stream funkciót és egy inicializálási hívást mutat:

A generált kód létrehoz egy szálat, amely azonnal végrehajtódik a CreateThread függvény befejezése után. Egy BOOL változó mutatója áthalad az áramló funkcióra. amely figyeli az áramlás állapotát; a zászló lehetővé teszi, hogy meghatározza a patak tevékenységét, és tárolja az értékeket TRUE (a szál aktív) vagy FALSE (a szál nem aktív).

Amikor a menet befejeződött, jelezve, hogy az áramlás már nem aktív (írásban FALSE az előzőekben említett logikai változó), és befejezi a munkafolyamat kihívás ExitThread funkciót. amely egyetlen paramétert ad - a szál befejezésének kódját, vagyis azt a számot, amely tájékoztatja a végrehajtás okát. A legtöbb esetben biztonságosan használhatja az ExitThread hívás 0 értékét.

Tény, hogy egy szál egyszerűen egy olyan funkció, amely egyidejűleg működik az alkalmazással. A szálak használatával kapcsolatban lásd a 4. fejezetet.

Kritikus szakaszok

Mivel a Windows egy többfeladatos rendszer, az egyéni alkalmazások zavarhatják egymást, különösen a több szálat használó alkalmazásokat. Mi van akkor, ha egy szál kitölti a fontos adatokat tartalmazó struktúrát, és egy másik szál egyszerre szeretné megváltoztatni vagy olvasni ezeket az adatokat?

Vannak módok annak biztosítására, hogy ha szükséges, csak egy szál kap teljes körű ellenőrzést, és ez a módszer a kritikus szakaszok használata. Amikor aktiválódik, a kritikus szakasz letiltja az összes többi szál próbál hozzáférni a megosztott memóriát (memória által használt alkalmazások összes témáját), ezáltal lehetővé téve az áramlás egymaga változtatni az alkalmazás adatait, nem kell aggódni interferencia más szálak. A kritikus szakasz használatához először nyilatkoznia kell és inicializálnia kell azt:

Ezt követően beírhatja a kritikus részt, feldolgozhatja az adatokat és elhagyhatja a kritikus szakaszt, amint az az alábbi példában látható:

Ha már nincs szükség kritikus szakaszra (például amikor az alkalmazás leáll), akkor fel kell szabadítania a hívást:

Noha a kritikus szakaszok részletesebben elmondhatók, erre nincs szükség. Nagyon könnyű használni őket, és többszálas alkalmazásokra van szükségük. Csak egy szabályt kell megjegyeznünk - győződjön meg arról, hogy a kritikus szakaszban lévő kód gyorsan végrehajtásra kerül; blokkolja a rendszerfolyamatokat, és ha a program túl hosszú ideig fut, akkor rendszerösszeomláshoz vezethet.

COM használata

A COM használatával olyan szoftverkomponenseket hozhat létre, amelyek funkciói kompatibilisek az összes programmal. Vegye például az Internet Explorer programot. Fogadok, hogy nem tudja, hogy az eszköztár és a böngészőablak COM objektumok. Ezenfelül használhatja ezeket az objektumokat az alkalmazásaiban is!

Bár ez jó indok a COM használatának elindításához, annál kényelmesebb a DirectX; A DirectX teljesen COM objektumból áll.

A COM indítása

A COM objektumok használatához inicializálnia kell a COM rendszert. A következő két funkció használható a COM inicializálására:

Mindkét funkció elvégzi a feladatot, de ha az alkalmazás többszálas, akkor a második funkciót, a CoInitializeEx-ot kell használnia. Mivel a dwCoInit paraméterben meg kell adnia a COINIT_MULTITHREADED jelölést. annak érdekében, hogy a COM rendszer megfelelően működjön.

Amikor befejezte a COM rendszert, akkor kapcsolja ki a CoUninitialize funkcióval. paraméterek nélkül:

Minden CoInitialize vagy CoInitializeEx hívásnak külön CoUninitialize hívással kell rendelkeznie. Ha kétszer hívja a CoInitialize-ot (ez megengedett), két CoUnitialize hívásra van szükség. Ezt a következő kódrészlet szemlélteti:

Az IUnknown az összes COM interfész alapszintje. Ez csak három funkciót tartalmaz: AddRef. Release és QueryInterface. Az AddRef szükség esetén inicializálja és növeli a számlálót, és megmutatja, hogy az osztály egy példányát hányszor hozták létre. A Visszajátszási funkcióhoz tartozó hívások számának meg kell egyeznie a referenciaszám értékével. Az objektum példány által használt erőforrás.

Ne keverd össze az osztályokat, az interfészeket és az objektumokat! Egy objektum egy osztály egy példánya. Egy felület egy objektum által biztosított funkciókészlet (más szavakkal, a felületek lehetővé teszik az objektummal való interakciót).

A harmadik függvény, a QueryInterface. az objektum által kínált objektumokhoz való hozzáférést használja, beleértve az új verziókat is. Ez a helyzet akkor fordulhat elő, ha több objektum verziója felszabadul, mint például a DirectX esetében. Még mindig használhatja a régi felületeket, és újakat is elérhet, ezeket meg kell kérnie. Ha az új felület létezik, az objektum visszaad egy mutatót; egyébként a QueryInterface visszaadja a NULL értéket. jelezve, hogy nincs interfész vagy hiba.

A funkciónak vissza kell térnie a HRESULT típusú értékre. hibajelzést vagy sikeres befejezést jelez. Ahhoz, hogy bármilyen értéket ki a COM-objektum, akkor át egy mutató egy változó (ami lehet egy szó vagy dupla szavas - bájt és egyéb nem támogatott), hogy a funkció és használja az index vissza értéket, hogy belül van a tárgy.

Példaként lehet létrehozni egy egyszerű tárgy (örökölt IUnknown), amely megkapja a két szám, összeadja őket össze, és elhelyezi az eredményt a változó által meghatározott harmadik paraméter:

Objektumok inicializálása és felszabadítása

A COM objektum használatához (a Loadable Windows könyvtár írása mellett) a CoCreateInstance funkció használatával kell létrehoznia:

Minden létrehozott COM objektumot végül fel kell szabadítani. IUnknown :: Release ilyen paraméterek nélkül használható:

Miután kilépett az IAdd2 felületről. a következőképpen kell szabadítania:

Interfészek kérése

A COM egyik legjobb tulajdonsága a kompatibilitás hátránya. Ha van egy új COM objektum (új interfészeket tartalmaz), akkor az objektumon keresztül teljes hozzáférést kap a régi interfészekhez. A régi interfészek mentése biztosítja, hogy a kód megfelelően működjön még akkor is, ha a végfelhasználó telepítette a COM objektumok új verzióit. Ez azt is jelenti, hogy a régi interfészek új interfészeket kérhetnek.

Ezt az IUnknown :: QueryInterface módszerrel végezzük:

Mivel a lekérdezési funkciót hívó forrásobjektum már létrehozásra került, nem kell aggódnia az osztályazonosító megadásával kapcsolatban - csak adja meg a szükséges felület azonosítóját. Térjünk vissza a matematikai osztály objektumához, és feltételezzük, hogy megkapja az IAdd felületet, majd át kívánja venni az IAdd2 felületet:

Bár a COM komoly téma, a fenti információk elegendőek a DirectX használatának megkezdéséhez. A könyv másik fejezetében többet megtudhat a DirectX-ről, ezért változtassunk irányt és beszéljünk más fontos dolgokról a projektről - a program áramlását.

Kapcsolódó cikkek