Ohjelmointi

Java ja Win32 yhdistäminen: Uusi tapa kehittää Windows-sovelluksia

Uutismedia on keskittynyt viime viikkoina useisiin fuusioihin. Pankit, autoyritykset ja vähittäiskauppaketjut ovat ilmoittaneet sulautumisestaan. Voitteko kuvitella shokin, jos Sun Microsystems ja Microsoft koskaan päättävät sulautua? En usko, että meidän pitäisi pidättää hengitystä. Uskon kuitenkin, että Sun ja Microsoft voisivat oppia toisensa toisistaan. Loppujen lopuksi molemmat yritykset ovat kehittäneet hyviä tuotteita - nimittäin Java ja Win32. Mielestäni Java-oppimiskäyrä on paljon lyhyempi kuin C ++ -oppimiskäyrä. Samalla Win32 on yksi tärkeä syy siihen, miksi Microsoftilla on Windows 95 / NT -käyttö useilla miljoonalla tietokoneella. Vaikuttaa luonnolliselta yhdistää Java ja Win32, jotta kehittäjät saavat edun, jota he tarvitsevat parempien Windows-sovellusten luomiseen lyhyemmässä ajassa. Se on tämän artikkelin painopiste.

Alussa...

Ensimmäiset Windows-sovellukset kirjoitettiin C-kielellä. Vaikka C oli kunnossa pienille sovelluksille, kehittäjien oli vaikea käyttää tätä kieltä suurempien sovellusten järjestämiseen. Ongelma keskittyi Windows-viestintämalliin ja siihen, että C on pikemminkin jäsennelty kuin olio-kieli. Perinteiset sovellukset, jotka käyttävät C: tä, luovat pääikkunan ja määrittävät takaisinsoittotoiminnon (tunnetaan nimellä ikkuna menettely) tähän ikkunaan. Aina kun jotain seurausta tapahtui tälle ikkunalle, Windows laukaisi viestin ikkunalle kutsumalla ikkunamenettelyn. Ikkunaprosessi vastaisi tunnistamalla ensin viestin valtavan vaihtotapaustiedotteen avulla ja käsittelemällä sitten viestin. Kuten usein tapahtuu, tila olisi tallennettava paikallisten staattisten muuttujien tai globaalien muuttujien kautta. Suuri sovellus voi johtaa moniin tällaisiin muuttujiin. Tämä paradigma toimi hyvin pienemmissä sovelluksissa, mutta osoittautui haitalliseksi suuremmille sovelluksille. Jotain oli tehtävä.

C-kieli kehittyi strukturoidusta kielestä olio-kieleksi - kieleksi nimeltä C ++. Objektikeskeisen kielen mukava asia on, että se antaa kehittäjille mahdollisuuden mallintaa reaalimaailman kokonaisuuksia luonnollisemmalla tavalla käyttämällä esineitä.

Muutama vuosi sitten Microsoft julkaisi työkalun kehittäjille, jotka halusivat luoda Windows-sovelluksia C ++: lla. Tämä tuote tunnettiin nimellä Visual C ++. Yksi Visual C ++: n kanssa käyttöönotetuista ominaisuuksista oli Microsoft Foundation Classes (MFC) -sovelluskehys. MFC-kehys on kokoelma C ++ -luokkia, jotka Microsoftin kehittäjät ovat kirjoittaneet ja testanneet ja joka toteuttaa paljon Windowsin perustoimintoja. Monet ohjelmistokonseptit - työkaluriveistä ja tilarivistä Model-View-Controller -arkkitehtuuriin perustuvaan dokumenttinäkymämalliin - on toteutettu MFC: ssä. MFC: n idea on säästää aikaa kehityksen aikana käyttämällä MFC-koodia suurimmalle osalle sovelluksesta ja laajentamalla sitten MFC: tä tarjoamaan kyseisen sovelluksen ainutlaatuiset ominaisuudet - kapseloinnin, perimisen ja polymorfismin olennaisiin olennaisiin käsitteisiin.

Ohjelmistojen kehittäminen MFC: llä ei kuitenkaan ole helppo tehtävä. Kirjoittaakseen nykypäivän Windows-sovellukset C ++: lla ja MFC: llä kehittäjillä on oltava hyvä käsitys olio-ohjelmointikonsepteista, C ++ -syntaksista ja erityispiirteistä, Windows-sovellusliittymistä ja MFC: stä.

Ihannetapauksessa kehittäjät tarvitsevat yhden kielen ja alustan, jonka avulla he voivat kirjoittaa sovelluksia vain kerran ja ottaa ne sitten käyttöön kaikkialla. Yrittäessään vastata tähän tarpeeseen, Sun on ottanut käyttöön alustan neutraalit versiot monista Windows-sovellusliittymistä Java-sovelluksen ainutlaatuisten sovellusliittymien (kuten Java-kortin) lisäksi. Tiedostojen hallintaa, postia, apua, multimediaa ja tietoturvaa käsittelevillä sovellusliittymillä on vastaavia Windows-maailmassa. Tästä seuraa yksi merkittävä etu Windows-kehittäjille: Kehittäjät voivat keskittyä Java- ja sen sovellusliittymien oppimiseen sen sijaan, että oppisivat paljon Windows-sovellusliittymiä C ++: n ja MFC: n kanssa. Sitten he voivat käyttää Java-sovellusta Windows-sovellusten kehittämiseen. Näin.

Kutsu-sovellusliittymä

Java-suunnittelijat keksivät mekanismin saada Java-koodi puhumaan C ++ -koodiin. Tämä mekanismi käyttää C ++ -sovellusliittymien kokoelmaa, joka tunnetaan nimellä Java Native Interface (JNI). Useat näistä sovellusliittymistä on koottu yhteen, ja ne tunnetaan yhdessä nimellä Invocation API.

Kutsu-sovellusliittymä koostuu useista JNI-toiminnoista, joiden avulla kehittäjä voi upottaa Java-virtuaalikoneen (JVM) mielivaltaiseen natiivisovellukseen. Kun JVM on upotettu, natiivisovelluksella on pääsy koko JVM: ään tekemällä JNI-puheluita.

JVM luodaan puhelun kautta JNI_CreateJavaVM () toiminto. Tämä toiminto vie osoittimen kohtaan a JDK1_1InitArgs rakenne argumenttina. Tämä rakenne tarjoaa JVM: n oletusasetukset. Oletukset voidaan ohittaa.

Oletusasetusten saamiseksi toinen JNI-toiminto, JNI_GetDefaultJavaVMInitArgs (), on soitettava. Tämä toiminto vie osoittimen JDK1_1InitArgs rakenne argumenttina. Tyypillinen soittosarja näkyy seuraavassa luettelossa:

JDK1_1InitArgs vm_args; vm_args.version = 0x00010001; JNI_GetDefaultJavaVMInitArgs (& vm_args); 

Versiokenttä on määritettävä ennen soittamista JNI_GetDefaultJavaVMInitArgs (). Tämä kenttä varmistaa, että sovellus käyttää oikeaa JVM: ää. Arvo 0x00010001 koodaa vaaditun JVM: n pääversionumeron korkeilla 16 bitillä ja pienen versionumeron matalilla 16 bitillä. 0x00010001-arvo tarkoittaa, että kaikki JVM, joiden versionumero on 1.1.2 tai uudempi, upotetaan sovellukseen.

Useat mielenkiintoiset kentät käsittävät JDK1_1InitArgs rakenne, mutta ainoa kenttä, jonka mainitsemme tässä artikkelissa, on kenttä, joka tunnetaan nimellä luokkatie. Tämä kenttä on tärkeä, koska se kertoo JVM: lle, missä class.zip ja sovellusluokan tiedostot sijaitsevat.

Kun JDK1_1InitArgs rakenne on alustettu, JVM voidaan luoda kutsun kautta JNI_CreateJavaVM (), kuten seuraavassa luettelossa on esitetty:

JavaVM * jvm; JNIEnv * env; rc = JNI_CreateJavaVM (& jvm, & env, & vm_args); 

Tässä vaiheessa JNI toimii FindClass () ja CallStaticVoidMethod () kutsutaan etsimään sopiva Java-aloitusluokka ja aloitustapa.

Kun JVM: ää ei enää tarvita, se tuhotaan kutsusta TuhoaJavaVM (), kuten seuraavassa luettelossa.

jvm-> TuhoaJavaVM () 

Joten miten Invocation-sovellusliittymä antaa meille mahdollisuuden luoda Win32-sovelluksia Java-sovelluksella? Seuraava esimerkki antaa vastauksen.

Esimerkki

Päätin luoda PKZIP: n kaltaisen Win32-konsolisovelluksen, mutta sovellukseni olisi hieman yksinkertaisempi. Se tarjoaisi vain mahdollisuuden luetteloida kaikki zip-arkistossa olevat tiedostot ja purkaa tiedostot. Sovellukseni käynnistetään komentoriviltä seuraavalla syntaksilla:

c: \> zip [-x-tiedosto] zip 

jonka mukaan -x on uuttolippu, tiedosto on purettavan tiedoston nimi ja postinumero on arkiston nimi zip-laajennuksella tai ilman sitä.

Seuraava luettelo näyttää C ++ -lähdekoodin zip.cpp. Tämä koodi toteuttaa ZIP-suoritettavan ohjaimen. Tämä ohjain lataa JVM: n, jäsentää komentoriviargumentit, etsii POSTINUMERO luokan tiedosto, etsii päämenetelmän POSTINUMERO luokan tiedosto, käynnistää päämenetelmän (välittää argumenttiluettelon tälle menetelmälle) ja purkaa JVM: n.

// ================================================== === // zip.cpp // // ZIP-suoritettava ohjain // // tukee Java Virtual Machine (JVM) 1.1.2 -käyttöjärjestelmää tai uudempaa // ================= ================================== # sisällyttää # sisällyttää # sisällyttää # sisällyttää # määritellä BUFSIZE 80 // == ================================================= // Käsittelijä / / // Console Control Handler // // Ohita kaikki yritykset sammuttaa sovellus. // // Argumentit: // // dwCtrlType - ohjaustapahtuman tyyppi // // Return: // // TRUE (ohita tapahtuma) // =================== ============================== BOOL-käsittelijä (DWORD dwCtrlType) {return TOSI; } // ========================================= // // // // Zip Suoritettava ohjaimen alkupiste // // Argumentit: // // argc - komentoriviargumenttien lukumäärä // argv - komentoriviargumenttien taulukko // // Return: // // 0 (onnistuminen) tai 1 (epäonnistuminen) / / ======================================= int int (int argc, char * argv [ ]) {sis. jint ret; JNIEnv * env; JavaVM * jvm; jclass clazz; jmethodID keskellä; JDK1_1InitArgs vm_args; char szBuffer [BUFSIZE], szClassPath [BUFSIZE * 2 + 15]; // Estää sovelluksen sammumista Ctrl-Break- tai Ctrl-C-näppäinten painallusten, // ikkunan sulkemispainikkeen napsautusten, käyttäjän kirjautumisen tai järjestelmän sammutuksen vuoksi. SetConsoleCtrlHandler (((PHANDLER_ROUTINE) Handler, TOSI); // Hae oletusalustusargumentit JVM-versiolle 1.1.2 tai uudemmalle. vm_args.version = 0x00010001; JNI_GetDefaultJavaVMInitArgs (& vm_args); // Kerro JVM: lle, mistä löydät sovellusluokan tiedostot ja class.zip. GetPrivateProfileString ("CONFIG", "PATH", ".", SzBuffer, 80, "zip.ini"); wsprintf (szClassPath, "% s;% s \ class.zip;", szBuffer, szBuffer); vm_args.classpath = szClassPath; // Yritetään luoda JVM-ilmentymä. if ((ret = JNI_CreateJavaVM (& jvm, & env, & vm_args)) NewStringUTF (""); jobjectArray str_array = env-> NewObjectArray (argc - 1, env-> FindClass ("java / lang / String"), jstr); (i = 1; i NewStringUTF (argv [i])) == 0) {fprintf (stderr, "Muisti loppui \ n"); paluu 1; } env-> SetObjectArrayElement (str_array, i - 1, jstr); } // Yritä paikantaa zip-luokka. if ((clazz = env-> FindClass ("zip")) == 0) {fprintf (stderr, "Zip-luokkaa ei löydy. Poistuminen ... \ n"); paluu 1; } // Yritä paikantaa zip-luokan päämenetelmä. if ((mid = env-> GetStaticMethodID (clazz, "main", "([Ljava / lang / String;) V")) == 0) {fprintf (stderr, "Päämenetelmää ei löydy. Poistuminen. .. \ n "); paluu 1; } // Käynnistä päämenetelmä. env-> CallStaticVoidMethod (clazz, mid, str_array); // Tuhoa JVM-ilmentymä. jvm-> TuhoaJavaVM (); paluu 0; } 

Huomaa puhelu Win32: lle GetPrivateProfileString () toiminto. Tämä toiminto etsii tiedostoa nimeltä zip.ini (joka sijaitsi Windowsin hakemistossa - yleensä c: \ Windows Windows 95: ssä tai c: \ winnt Windows NT: ssä). Tämän tiedoston tarkoituksena on pitää polku, johon ZIP-sovellus on asennettu. JVM etsii tästä sijainnista class.zip- ja sovellusluokatiedostot (riippumatta siitä, mistä ZIP-sovellusta kutsutaan).

Toinen huomioitava asia on kutsu SetConsoleCtrlHandler () Win32-sovellusliittymä. Tämä sovellusliittymä estää Ctrl-C- tai Ctrl-Break-näppäinpainalluksia - muiden tapahtumien lisäksi - pysäyttämästä sovellusta ennen kuin se on valmis. Tämä voi olla tai ei olla toivottavaa sovelluksesta riippuen.

ZIP-sovellus on kirjoitettu Java-kielellä. Se antaa käyttäjille mahdollisuuden tarkastella zip-arkistotiedostojen sisältöä sekä mahdollisuuden poimia yksittäisiä tiedostoja näistä arkistoista. Seuraava luettelo sisältää ZIP-lähdekoodin.