Programavimas

„Java“ ir „Win32“ sujungimas: naujas būdas kurti „Windows“ programas

Naujienų žiniasklaida pastarosiomis savaitėmis sutelkė dėmesį į daugelį susijungimų. Bankai, automobilių korporacijos ir prekybos tinklai paskelbė, kad jie jungiasi. Ar galite įsivaizduoti šoką, jei „Sun Microsystems“ ir „Microsoft“ kada nors nuspręstų susijungti? Na, nemanau, kad turėtume sulaikyti kvėpavimą. Vis dėlto manau, kad „Sun“ ir „Microsoft“ galėtų išmokti vieną ar kitą dalyką. Juk abi kompanijos sukūrė gerus produktus - būtent „Java“ ir „Win32“. Mano nuomone, „Java“ mokymosi kreivė yra daug trumpesnė nei C ++ mokymosi kreivė. Tuo pačiu metu „Win32“ yra viena svarbių priežasčių, kodėl „Microsoft“ naudoja „Windows 95 / NT“ daugelyje milijonų kompiuterių. Atrodo, kad natūralu sujungti „Java“ ir „Win32“, kad kūrėjai suteiktų pranašumų, reikalingų geresnėms „Windows“ programoms kurti per trumpesnį laiką. Tai yra šio straipsnio dėmesys.

Pradžioje...

Pirmosios „Windows“ programos buvo parašytos C kalba. Nors mažoms programoms C buvo gerai, kūrėjams buvo sunku naudoti šią kalbą organizuojant didesnes programas. Problema buvo susijusi su „Windows“ susirašinėjimo modeliu ir tuo, kad C yra struktūrinė, o ne į objektą orientuota kalba. Tradicinės programos, naudojančios C, sukurs pagrindinį langą ir priskirs atgalinio skambinimo funkciją (žinomą kaip lango procedūra) į šį langą. Kai tik kas nors atsitiks su šiuo langu, „Windows“ iškviesdavo pranešimą į langą iškviesdama lango procedūrą. Lango procedūra būtų atsakyta pirmiausia nustatant pranešimą per didžiulį keitimo atvejį ir tada apdorojant pranešimą. Kaip dažnai būna, būseną reikėtų išsaugoti per vietinius statinius ar visuotinius kintamuosius. Didelė programa gali sukelti daug tokių kintamųjų. Ši paradigma gerai veikė mažesnėms programoms, tačiau pasirodė esanti žalinga didesnėms programoms. Kažką reikėjo padaryti.

C kalba iš struktūrinės kalbos virto į objektą orientuota kalba - kalba, vadinama C ++. Gražus dalykas kalbant apie objektą yra tai, kad ji suteikia kūrėjams galimybę natūraliau modeliuoti realaus pasaulio objektus, naudojant objektus.

Prieš keletą metų „Microsoft“ išleido įrankį kūrėjams, norintiems sukurti „Windows“ programas naudojant „C ++“. Šis produktas tapo žinomas kaip „Visual C ++“. Viena iš „Visual C ++“ pristatytų funkcijų buvo programos pagrindas, žinomas kaip „Microsoft Foundation Classes“ (MFC). MFC sistema yra „C ++“ klasių rinkinys, kurį parašė ir išbandė „Microsoft“ kūrėjai, įgyvendinantys daugybę pagrindinių „Windows“ funkcijų. Daugelis programinės įrangos koncepcijų - nuo įrankių juostų ir būsenos juostų iki dokumentų peržiūros modelio, pagrįsto „Model-View-Controller“ architektūra - buvo įdiegtos MFC. MFC idėja yra sutaupyti laiko kūrimo metu naudojant MFC kodą daugumai programų ir tada išplėsti MFC, kad būtų suteiktos unikalios programos galimybės - naudojant pagrindines objektyvias kapsuliavimo, paveldėjimo ir polimorfizmo koncepcijas.

Tačiau programinės įrangos kūrimas naudojant MFC nėra lengva užduotis. Kad kūrėjai galėtų rašyti šiandienos „Windows“ programas naudodami C ++ ir MFC, kūrėjai turi gerai suprasti objektinio programavimo koncepcijas, C ++ sintaksę ir ypatumus, „Windows“ API ir MFC.

Idealiu atveju kūrėjams reikia vienos kalbos ir platformos, kuri leistų rašyti programas tik vieną kartą, o paskui jas įdiegti visur. Siekdama patenkinti šį poreikį, „Sun“, be unikalių „Java“ API (pvz., „Java Card“), įdiegė daugelio „Windows“ API versijų neutralias versijas. API, susijusios su failų valdymu, paštu, pagalba, daugialypės terpės ir sauga, turi analogų „Windows“ pasaulyje. Tai suteikia vieną didelę naudą „Windows“ kūrėjams: užuot išmokę daug „Windows“ API kartu su C ++ ir MFC, kūrėjai gali sutelkti dėmesį į „Java“ ir jos API mokymąsi. Tada jie gali naudoti „Java“ „Windows“ programoms kurti. Štai kaip.

Kvietimo API

„Java“ dizaineriai sukūrė mechanizmą, kaip gauti „Java“ kodą kalbėti su C ++ kodu. Šis mechanizmas naudoja C ++ API kolekciją, vadinamą „Java Native Interface“ (JNI). Keletas šių API buvo sujungtos ir bendrai vadinamos „Invocation“ API.

„Invocation“ API sudaro kelios JNI funkcijos, leidžiančios kūrėjui įterpti „Java“ virtualiąją mašiną (JVM) į savavališką vietinę programą. Įterpusi JVM, vietinė programa turi prieigą prie viso JVM, atlikdama JNI skambučius.

JVM sukurtas paskambinus į JNI_CreateJavaVM () funkcija. Ši funkcija nukreipia žymeklį į a JDK1_1InitArgs struktūra kaip argumentas. Ši struktūra pateikia numatytuosius JVM nustatymus. Numatytuosius nustatymus galima nepaisyti.

Norint gauti numatytuosius nustatymus, reikia dar vieną JNI funkciją, JNI_GetDefaultJavaVMInitArgs (), reikia paskambinti. Ši funkcija nukreipia žymeklį į JDK1_1InitArgs struktūra kaip argumentas. Tipinė skambučių seka rodoma šiame sąraše:

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

Versijos laukas turi būti nustatytas prieš skambinant JNI_GetDefaultJavaVMInitArgs (). Šis laukas užtikrina, kad programa naudoja teisingą JVM. 0x00010001 reikšmė užkoduoja reikiamo JVM pagrindinį versijos numerį dideliuose 16 bitų, o mažosios versijos numerius - mažuose 16 bitų. 0x00010001 reikšmė reiškia, kad bet koks JVM, kurio versijos numeris yra 1.1.2 ar didesnis, bus įtrauktas į programą.

Keletą įdomių sričių sudaro JDK1_1InitArgs struktūrą, tačiau vienintelis laukas, kurį paminėsime šiame straipsnyje, yra laukas, žinomas kaip klasės kelias. Šis laukas yra svarbus, nes jis nurodo JVM, kur yra class.zip ir programos klasės failai.

Kartą JDK1_1InitArgs struktūra buvo inicijuota, JVM galima sukurti paskambinus JNI_CreateJavaVM (), kaip parodyta šiame sąraše:

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

Šiuo metu JNI veikia „FindClass“ () ir „CallStaticVoidMethod“ () būtų pakviestas rasti tinkamą „Java“ pradžios klasę ir pagrindinį pradinį metodą.

Kai JVM nebereikalingas, jis sunaikinamas paskambinus „DestroyJavaVM“ (), kaip šiame sąraše.

jvm-> SunaikintiJavaVM () 

Taigi, kaip „Invocation“ API leidžia mums sukurti „Win32“ programas naudojant „Java“? Šis pavyzdys pateikia atsakymą.

Pavyzdys

Aš nusprendžiau sukurti „Win32“ konsolės programą, panašią į PKZIP, bet mano programa būtų šiek tiek paprastesnė. Tai suteiktų tik galimybę išvardyti visus failus zip archyve ir išgauti failus. Mano programa bus paleista iš komandinės eilutės naudojant šią sintaksę:

c: \> zip [-x failas] zip 

kuriuo -x yra ištraukimo vėliava, failą yra išskleidžiamo failo pavadinimas ir užtrauktukas yra archyvo pavadinimas su pridedamu ar be jo.

Šiame sąraše rodomas C ++ šaltinio kodas zip.cpp. Šis kodas įdiegia ZIP vykdomąjį tvarkyklę. Šis tvarkyklė įkelia JVM, analizuoja komandinės eilutės argumentus, suranda ZIP klasės failą, suranda pagrindinį metodą ZIP klasės failą, paleidžia pagrindinį metodą (perduoda argumentų sąrašą šiam metodui) ir iškrauna JVM.

// ================================================== === // zip.cpp // // ZIP vykdomoji tvarkyklė // // palaiko „Java Virtual Machine“ (JVM) 1.1.2 ar naujesnę versiją = ================= ================================== # įskaičiuoti # įtraukti # įskaičiuoti # įskaičiuoti # apibrėžti BUFSIZE 80 // == =============================================== // // tvarkytojas / / // „Console Control Handler“ // // Nepaisykite visų bandymų išjungti programą. Argumentai: // // dwCtrlType - valdymo įvykio tipas // // Return: // // TRUE (ignoruoti įvykį) // =================== ============================== „BOOL Handler“ (DWORD dwCtrlType) {return TRUE; } // ======================================= // // pagrindinis // // „Zip“ Vykdomas tvarkyklės įvesties taškas // // Argumentai: // // argc - komandinės eilutės argumentų skaičius // argv - komandų eilutės argumentų masyvas // // Return: // // 0 (sėkmė) arba 1 (nesėkmė) / / ======================================= int pagrindinis (int argc, char * argv [ ]) {int i; jint ret; JNIEnv * env; „JavaVM * jvm“; jclass clazz; jmethodID vidurys; JDK1_1InitArgs vm_args; char szBuffer [BUFSIZE], szClassPath [BUFSIZE * 2 + 15]; // Neleiskite programai išsijungti dėl „Ctrl-Break“ arba „Ctrl-C“ paspaudimų, // lango uždarymo mygtuko paspaudimų, vartotojo atsijungimo ar sistemos išjungimo. „SetConsoleCtrlHandler“ ((PHANDLER_ROUTINE) tvarkytuvas, TIKRA); // Gaukite numatytuosius JVM 1.1.2 ar naujesnės versijos inicializavimo argumentus. vm_args.version = 0x00010001; JNI_GetDefaultJavaVMInitArgs (& vm_args); // Pasakykite JVM, kur rasti programos klasės failus ir class.zip. „GetPrivateProfileString“ („CONFIG“, „PATH“, „.“, SzBuffer, 80, „zip.ini“); wsprintf (szClassPath, "% s;% s \ class.zip;", szBuffer, szBuffer); vm_args.classpath = szClassPath; // Bandymas sukurti JVM egzempliorių. 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, "Atmintyje nėra \ n"); grąžinti 1; } env-> SetObjectArrayElement (str_array, i - 1, jstr); } // Bandymas rasti zip klasę. if ((clazz = env-> FindClass ("zip")) == 0) {fprintf (stderr, "Nepavyksta rasti zip klasės. Išeinama ... \ n"); grąžinti 1; } // Bandymas surasti zip klasės pagrindinį metodą. if ((mid = env-> GetStaticMethodID (clazz, "main", "([Ljava / lang / String;) V")) == 0) {fprintf (stderr, "Negaliu rasti pagrindinio metodo. Išeinama. .. \ n "); grąžinti 1; } // Paleisti pagrindinį metodą. env-> CallStaticVoidMethod (clazz, mid, str_array); // Sunaikinti JVM egzempliorių. jvm-> SunaikintiJavaVM (); grąžinti 0; } 

Atkreipkite dėmesį į „Win32“ skambutį „GetPrivateProfileString“ () funkcija. Ši funkcija ieško failo, vadinamo zip.ini (kuris būtų „Windows“ kataloge - paprastai „c: \ windows“, kai naudojama „Windows 95“, arba „c: \ winnt“, kai naudojama „Windows NT“). Šio failo tikslas yra išlaikyti kelią, kuriame įdiegta ZIP programa. JVM šioje vietoje ieškos class.zip ir application class failų (nesvarbu, iš kur skambinama ZIP programa).

Kitas dalykas, į kurį reikia atkreipti dėmesį, yra skambutis į „SetConsoleCtrlHandler“ () „Win32“ API. Ši API neleidžia „Ctrl-C“ arba „Ctrl-Break“ klavišų paspaudimams (be kitų įvykių) sustabdyti programą prieš jai baigiant. Tai gali būti pageidautina arba ne, priklausomai nuo taikymo.

ZIP programa parašyta Java kalba. Tai suteikia vartotojams galimybę peržiūrėti zip archyvo failų turinį, taip pat galimybę išgauti atskirus failus iš šių archyvų. Šiame sąraše yra ZIP kodas.