Programmering

Fletning af Java og Win32: En ny måde at udvikle Windows-applikationer på

Nyhedsmedierne har fokuseret på en række fusioner i de seneste uger. Banker, bilfirmaer og detailkæder har meddelt, at de fusionerer. Kan du forestille dig chokket, hvis Sun Microsystems og Microsoft nogensinde beslutter at fusionere? Jeg tror ikke, vi skal holde vejret. Jeg tror dog, at Sun og Microsoft kunne lære en ting eller to af hinanden. Når alt kommer til alt har begge virksomheder udviklet gode produkter - nemlig Java og Win32. Efter min mening er Java-indlæringskurven meget kortere end C ++ indlæringskurven. Samtidig er Win32 en vigtig årsag til, at Microsoft har Windows 95 / NT kørende på nogle millioner af pc'er. Det virker kun naturligt at fusionere Java og Win32 for at give udviklere den fordel, de har brug for til at skabe bedre Windows-applikationer på kortere tid. Det er fokus for denne artikel.

I begyndelsen...

De første Windows-applikationer blev skrevet på C-sproget. Mens C var okay for små applikationer, fandt udviklere det vanskeligt at bruge dette sprog til at organisere større applikationer. Problemet centreret omkring Windows messaging-modellen og det faktum, at C er et struktureret snarere end et objektorienteret sprog. Traditionelle applikationer, der bruger C, opretter et hovedvindue og tildeler en tilbagekaldsfunktion (kendt som en vinduesprocedure) til dette vindue. Når der skete noget af konsekvenser for dette vindue, sendte Windows en besked til vinduet ved at kalde vinduesproceduren. Vinduesproceduren svarer ved først at identificere meddelelsen via en enorm switch-case-erklæring og derefter behandle meddelelsen. Som det ofte er tilfældet, skal tilstand gemmes via lokale statiske variabler eller globale variabler. En stor applikation kan resultere i mange sådanne variabler. Dette paradigme fungerede godt til mindre applikationer, men viste sig at være skadeligt for større applikationer. Noget skulle gøres.

C-sproget udviklede sig fra et struktureret sprog til et objektorienteret sprog - et sprog kaldet C ++. Det pæne ved et objektorienteret sprog er, at det giver udviklere mulighed for at modellere virkelige enheder på en mere naturlig måde ved at bruge objekter.

For et par år siden frigav Microsoft et værktøj til udviklere, der ønskede at oprette Windows-applikationer ved hjælp af C ++. Dette produkt blev kendt som Visual C ++. En af funktionerne introduceret med Visual C ++ var en applikationsramme kendt som Microsoft Foundation Classes (MFC). MFC-rammen er en samling af C ++ - klasser, skrevet og testet af Microsofts udviklere, der implementerer en masse grundlæggende Windows-funktionalitet. Mange softwarekoncepter - fra værktøjslinjer og statuslinjer til en dokumentvisningsmodel baseret på Model-View-Controller-arkitekturen - er blevet implementeret i MFC. Ideen bag MFC er at spare tid under udvikling ved at bruge MFC-kode til det meste af applikationen og derefter udvide MFC til at give applikationens unikke muligheder - via de grundlæggende objektorienterede begreber indkapsling, arv og polymorfisme.

At udvikle software med MFC er dog ikke en let opgave. For at kunne skrive nutidens Windows-applikationer ved hjælp af C ++ og MFC skal udviklere have en god forståelse af objektorienterede programmeringskoncepter, C ++ syntaks og særegenheder, Windows API'er og MFC.

Ideelt set har udviklere brug for et enkelt sprog og en platform, der giver dem mulighed for at skrive applikationer kun en gang og derefter implementere dem overalt. I et forsøg på at imødekomme dette behov har Sun implementeret platformneutrale versioner af mange Windows API'er ud over API'er, der er unikke for Java (såsom Java Card). API'er, der beskæftiger sig med filhåndtering, mail, hjælp, multimedie og sikkerhed, har modstykker i Windows-verdenen. Dette resulterer i en stor fordel for Windows-udviklere: I stedet for at lære mange Windows API'er sammen med C ++ og MFC kan udviklere fokusere på at lære Java og dets API'er. Derefter kan de bruge Java til at udvikle Windows-applikationer. Sådan gør du.

Invokations-API'en

Java-designerne kom med en mekanisme til at få Java-kode til at tale med C ++ -koden. Denne mekanisme bruger en samling af C ++ API'er kendt som Java Native Interface (JNI). Flere af disse API'er er samlet og er samlet kendt som Invocation API.

Invocation API består af flere JNI-funktioner, der gør det muligt for udvikleren at integrere den virtuelle Java-maskine (JVM) i en vilkårlig oprindelig applikation. Med JVM integreret har den oprindelige applikation adgang til hele JVM ved at foretage JNI-opkald.

JVM oprettes via et opkald til JNI_CreateJavaVM () fungere. Denne funktion tager en markør til en JDK1_1InitArgs struktur som argument. Denne struktur giver standardindstillinger for JVM. Standardindstillingerne kan tilsidesættes.

For at få standardindstillingerne skal en anden JNI-funktion, JNI_GetDefaultJavaVMInitArgs (), skal kaldes. Denne funktion tager en markør til JDK1_1InitArgs struktur som argument. En typisk opkaldssekvens vises i følgende liste:

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

Versionsfeltet skal indstilles inden opkald JNI_GetDefaultJavaVMInitArgs (). Dette felt sikrer, at den korrekte JVM bruges af applikationen. En værdi på 0x00010001 koder hovedversionnummeret for den krævede JVM i de høje 16 bit og det mindste versionsnummer i de lave 16 bit. Værdien 0x00010001 betyder, at enhver JVM, hvis versionsnummer er 1.1.2 eller højere, vil blive integreret i applikationen.

Flere interessante felter omfatter JDK1_1InitArgs struktur, men det eneste felt, vi nævner i denne artikel, er det felt, der er kendt som klassesti. Dette felt er vigtigt, fordi det fortæller JVM, hvor classes.zip og applikationsklassens filer ligger.

En gang JDK1_1InitArgs struktur er blevet initialiseret, kan JVM oprettes via et opkald til JNI_CreateJavaVM (), som vist i følgende liste:

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

På dette tidspunkt fungerer JNI FindClass () og CallStaticVoidMethod () kaldes for at finde den passende Java-startklasse og starthovedmetoden.

Når JVM ikke længere er påkrævet, ødelægges den af ​​et opkald til DestroyJavaVM (), som i den følgende liste.

jvm-> DestroyJavaVM () 

Så hvordan tillader Invocation API os at oprette Win32-applikationer ved hjælp af Java? Følgende eksempel giver et svar.

Et eksempel

Jeg besluttede at oprette en Win32-konsolapplikation svarende til PKZIP, men min applikation ville være lidt enklere. Det giver kun muligheden for at liste alle filer i et zip-arkiv og udpakke filer. Min applikation startes fra kommandolinjen ved hjælp af følgende syntaks:

c: \> zip [-x fil] zip 

hvorved -x er udvindingsflagget, fil er navnet på den fil, der skal udpakkes, og lynlås er navnet på arkivet med eller uden zip-udvidelse.

Følgende liste viser C ++ kildekoden zip.cpp. Denne kode implementerer ZIP-eksekverbar driver. Denne driver indlæser JVM, analyserer kommandolinjeargumenterne, lokaliserer ZIP klassefil, lokaliserer hovedmetoden i ZIP klassefil, starter hovedmetoden (videresender listen til denne metode) og aflæsser JVM.

// =================================================== === // zip.cpp // // ZIP-eksekverbar driver // // Understøtter Java Virtual Machine (JVM) 1.1.2 eller højere // ================== =================================== # inkluderer # inkluderer # inkluderer # inkluderer # definer BUFSIZE 80 // == ================================================ // Handler / / // Console Control Handler // // Ignorer alle forsøg på at lukke applikationen. // // Argumenter: // // dwCtrlType - kontrolhændelsestype // // Return: // // TRUE (ignorer begivenhed) // =================== ================================ BOOL Handler (DWORD dwCtrlType) {returner SAND; } // ========================================== // hoved // // Zip Eksekverbart driverindgangspunkt // // Argumenter: // // argc - antal kommandolinjeargumenter // argv - matrix med kommandolinjeargumenter // // Retur: // // 0 (succes) eller 1 (fejl) / / ========================================= int main (int argc, char * argv [ ]) {int i; jint ret; JNIEnv * env; JavaVM * jvm; jclass clazz; jmethodID mid; JDK1_1InitArgs vm_args; char szBuffer [BUFSIZE], szClassPath [BUFSIZE * 2 + 15]; // Forhindre, at applikationen lukker ned på grund af Ctrl-Break eller Ctrl-C-tastetryk, // klik på vindueslukning, brugerlogoff eller systemlukning. SetConsoleCtrlHandler ((PHANDLER_ROUTINE) Handler, SAND); // Få standardinitialiseringsargumenter for JVM version 1.1.2 eller nyere. vm_args.version = 0x00010001; JNI_GetDefaultJavaVMInitArgs (& vm_args); // Fortæl JVM, hvor applikationsklassefiler og classes.zip skal findes. GetPrivateProfileString ("CONFIG", "PATH", ".", SzBuffer, 80, "zip.ini"); wsprintf (szClassPath, "% s;% s \ classes.zip;", szBuffer, szBuffer); vm_args.classpath = szClassPath; // Forsøg på at oprette en JVM-forekomst. hvis ((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, "Out of memory \ n"); returnere 1; } env-> SetObjectArrayElement (str_array, i - 1, jstr); } // Forsøg på at finde zip-klasse. hvis ((clazz = env-> FindClass ("zip")) == 0) {fprintf (stderr, "Kan ikke finde zip-klassen. Afslut ... \ n"); returnere 1; } // Forsøg på at finde zip-klassens hovedmetode. if ((mid = env-> GetStaticMethodID (clazz, "main", "([Ljava / lang / String;) V")) == 0) {fprintf (stderr, "Kan ikke finde hovedmetoden. Afslut. .. \ n "); returnere 1; } // Start hovedmetode. env-> CallStaticVoidMethod (clazz, mid, str_array); // Ødelæg JVM-forekomsten. jvm-> DestroyJavaVM (); returnere 0; } 

Bemærk opkaldet til Win32 GetPrivateProfileString () fungere. Denne funktion søger efter en fil, der hedder zip.ini (som ville være placeret i Windows-biblioteket - normalt c: \ windows under Windows 95 eller c: \ winnt under Windows NT). Formålet med denne fil er at holde stien, hvor ZIP-applikationen er installeret. JVM vil se på denne placering efter classes.zip og applikationsklassefiler (uanset hvor ZIP-applikationen kaldes fra).

En anden ting at bemærke er et opkald til SetConsoleCtrlHandler () Win32 API. Denne API forhindrer Ctrl-C eller Ctrl-Break tastetryk - ud over andre begivenheder - i at stoppe applikationen, før den er færdig. Dette kan eller måske ikke være ønskeligt afhængigt af applikationen.

ZIP-applikationen er skrevet i Java. Det giver brugerne mulighed for at se indholdet af zip-arkivfiler samt muligheden for at udtrække individuelle filer fra disse arkiver. Følgende liste indeholder kildekoden til ZIP.