Fakultet Informacionih Tehnologija Beograd 2010.

SE211 – Izrada softvera Domaći zadatak

Java/C++ integracija
Java/C++ integration

Student:

Asistent:

Nikola Stamatović 204

Nedeljko Pavlović

SE211 – Domaći zadatak: Java/C++ integracija

Sadržaj
Abstrakt......................................................................................................................................................3 Uvod...........................................................................................................................................................4 Java vs. C++...............................................................................................................................................5 Načini integracije.......................................................................................................................................5 Komandna linija................................................................................................................................5 Komunikacija preko mreže...............................................................................................................6 Soketi.......................................................................................................................................7 Baze podataka.......................................................................................................................10 CORBA.................................................................................................................................12 Apache Thrift........................................................................................................................18 Sloj interfejsa..................................................................................................................................21 Java Native Interface – JNI...................................................................................................21 Java Native Access – JNA.....................................................................................................22 Simplified Wrapper and Interface Generator – SWIG..........................................................23 QTJambi................................................................................................................................24 Zaključak..................................................................................................................................................26 Sugestije za nastavak rada........................................................................................................................27 Literatura..................................................................................................................................................28

2

SE211 – Domaći zadatak: Java/C++ integracija

Abstrakt
Kratak dokument koji vodi kroz filozofiju, načine, tehnike i praktičnu primenu integracije dva najpoznatija jezika današnjice Jave i C++. Nakon filozofije i definisanja razloga potrebe integracije kao i njenih negativnih strana, uktatko su opisane najpoznatije, platformski nezavisne, tehnike integracije i dati segmenti koda spremni za implementaciju. Pored osnovnih tehnika koje uključuju svima poznatu komunikaciju preko pisanja i čitanja fajla koja nije opisana zbog njene banalnosti, pozivanje preko komandne linije, komunikaciju preko soketa, baza podataka, opisane su kroz teoriju i praksu kompleksnije i modernijie poput CORBA, Thrift, JNI, JNA, SWIG i QTJambi. Ovaj dokument pruža brzu referencu vezanu za temu ili kratak uvod osobama koje su nove konceptu integracije. Dati segmenti koda nisu detaljno tumačeni jer se znanje Jave i C++ podrazumeva, te za više informacija možete posetiti lokacije priložene u poglavlju Literatura. Ključne reči: Java, C++, Integracija, Soket, Baza, CLI, CORBA, Thrift, JNI, JNA, SWIG, QT Jambi

3

SE211 – Domaći zadatak: Java/C++ integracija

Uvod
Svaki programski jezik je priča za sebe, počevši od toga da su ih razvijali različiti ljudi, sa različitim prohtevima u različitim okolnostima za različite svrhe. Oni su nastali kako bi olakšali rad svojih kreatora, a definicija pojma olakšanje varira od osobe do osobe kao što se da zaključiti. I sada se postavlja pitanje koje obično pitaju početnici u ovoj profesiji: “Koji je jezik najbolji?”. Često se rezočaraju kada im odgovorite da ne postoji programski jezik koji je najbolji ili pak da je svaki jezik najbolji u onome za šta je namenjen, ali u skladu s prethodno rečenim oba odgovora su prava. Javlja se još jedan zanimljiv fenomen, a to je da postoje iključivo Java programeri, isključivo C++, Python, C#... U industriji se pokazalo da uska specijalizacija obećava stabilnu karijeru, ali iskustvo me navodi da zaključim da ovakav pristup čini loše profesionalce. Programeri često zapadnu u zabludu da treba praktikovati i usavršavati samo jedan jezik ili tehnologiju, što je ekvivalnetno sa čovekom koji ulaže sve napore da ovlada samo čekićem od svih alata. Takvu osobu bi zvali samo kada je potrebno uraditi nešto u Javi ili zakucati ekser i takva osoba nije stručnjak već je alat. Svaki programski jezik je po osnovi sličan, tako da svako znanjem jednog kvalitetnog jezika je izuzetno lako naučiti sve ostale. Da to nije tako, postojanje UML-a (Unified Modeling Language) ili pseudo jezika, koji služe za modeliranje nezavisno od jezika, bi bilo apsurdno. Problem koji se javlja kada se u istom timu sretnu dva programera usko specijalizovana za dva različita jezika jeste da često ni jedan od njih nije svestan procesa integracije, t.j. procesa razvoja projekta koji se zasniva na kolaboraciji dva ili više jezika i tehnologija, tačnije vidova komunikacije između funkcionalnih celina budućeg sistema razvijenih u različitim tehnologijama. Imao sam prilike sresti laike koji su tvrdili da je nemoguća kolaboracija između dva programa u različitim jezicima, no svako ko bi malčice bolje razmislio shvatio bi da svaki programski jezik osposobljen metodama za pisanje i čitanje fajlova, komunikaciju sa komandnom linijom sistema, kao i mrežnu komunikaciju te je izuzetno lako zaključiti da ovim vidovima ovakvi programi veoma lako mogu komunicirati. S druge strane stavljamo pitanje performansi izvršenja određenih poslova koje jezik generički obavja, dakle sigurno je brži C++ program za parsing teksta od Javinog i za izradu i za izvršavanje ili vam je lakše i brže izraditi GUI pomoću QT-a nego Swing-a. Poučeni ovim, prilikom kvalitetnog razvoja sistema treba imati u vidu važnost vašeg vremena kao programera i vremena korisnika te se koristiti alatima koji će vam omogućiti kvalitan i brz put ka željenim rezultatima. No kako bi uopšte razmišljali o razvoju uz pomoć više jezika mora se pre svega sačiniti kvalitetan model sistema, počevši od ciljeva koje treba rešiti, okvirne definicije sistema i razbijanja istog na fukcionalne celine do izbora tehnologija koje će potkrepiti prohteve za performansama, stabilnošću, bezbednošću, fleksibilnošću sistema i njegovih programera. Pri tome, vidovima komunikacije između funkcionalnih celina se mora posvetiti posebna pažnja jer se na njima zasniva i kolaboracija stručnjaka uključenih u razvoj projekta. Integracija nije nužna već poželjna u koliko nemate vremena ni novca da zaposlite još programera ili trenirate vaš tim za tehnologiju izbora. Kroz dalji tekst biće predstavljene korisne multiplatformske tehnike integracije dva veoma popularna jezika današnjice Jave i C++-a, ali primetićete da mnoge od ovih tehnika ne zavise od ova dva jezika već se mogu primeniti u integraciji mnogih drugih. Potrebno je imati u vidu da integracija dolazi sa svojom cenom, u slučaju ova dva jezika to bi bio gubitak portabilnosti aplikacije, u nekom drugom možda dodatni interpreteri ili bilioteke, pa je nužno da integracija bude svesna odluka razvojnog tima.

4

SE211 – Domaći zadatak: Java/C++ integracija

Java vs. C++
Pošto smo okvirno definisali koje su prednosti i mane procesa integracije, kako bi uopšte počeli diskusiju o tehnikama integracije Jave i C++ moramo se ukratko osvrnuti na sličnosti i razlike ova dva jezika da bi lakše razumeli svrhu primene ovih tehnika. Jednom kompajlirani Java kod se prevodi u byte-code koji nakon svakog pokretanja biva interpretiran od strane Java Virtualne Mašine (JVM) koja je ujedno i glavna razlika između ova dva jezika. JVM je kompajlirana za mnoštvo platformi i dolazi u paketu sa standardnim Java bibliotekama koji zajedno čine Java Runtime Environment (JRE), samim tim na svakoj platformi gde se može instalirati javin runtime mogu se pokretati java aplikacije. Ovo je ogromna prednost, skraćuje vreme portovanja na druge platforme, ima kontrolu koda pri izvršavanju, automatsko uništavanje nepotrebnih objekata (garbage collecting) i omogućava veću bezbednost. No ovakav prstup odlazi s cenom znatno sporijeg inzvršavanja i nemogučnosti low level programiranja, dakle bez direktne komunikacije sa hardverom. Poželjno je pomenuti da Java nalaže objektno orjentisan pristup progoramiranju i samim tim traži od programera da razmišljaju modularno i prave fleksibilan kod. U cilju održanja OOP pristupa ukida višestruko nasleđivanje i globalne promenljive te je Singleton pattern često nužan. S druge strane C++ je programski jezik niskog noivoa koji zahteva kompajliranje za svaku arhitekturu proceosra. Kompajlirani C++ kod se direktno prevodi na mašinski jezik ali zbog veza između klasa razdvojenih u fajlove zauzima mnogo više prostora od byte koda. Logično je zaključiti da se mašinski jezik neopisivo brže izvršava nego byte code koji zahteva dodatnu interpretaciju i provere pa su performanse C++ programa primetno bolje od Javinih. C++ podržava aljkavi developement, tačnije dozvoljava strukturno programiranje, višestruka nasleđivanja i globalne promenljive, te razvoj aplikacija može biti brz ali i podložan greškama i bez mogučnosti ponovnog korišćenja koda (reusability). Već sada je jasno koje su prednosti integracije ova dva jezika, komunikacija sa hardverom, sjajne C++ biblioteke, performanse, ali još jednom treba skrenuti pažnju na gubitak portabilnosti ovakvih aplikacija.

Načini integracije
Komandna linija
Pretpostavimo da imate za zadatak sačiniti aplikaciju koja mora pokrenuti neki program ili skriptu na vašem računaru. Pravilnim razmišljanjem odmah ćete zaključiti da je pravi i najlakši način da ovo uradite pozivanjem programa iz komandne linije. Da li je ovo moguće? Odgovor je da. Ovaj tradicionalni i izuzetno utemeljeni alat interakcije sa računarskim sistemom vam omogućuje da ga koristite mnogo brže i efikasnije od grafičkog interfejsa, što Linux korisnici znaju najbolje, i naravno pravi programski jezici moraju biti osposobljeni za komunikaciju sa sistemom na ovaj način. Sledeće što bi moglo zabrinuti programera, jeste da li on može pokupiti konzolni output pozvanog programa, što je takođe moguće. Sada pretpostavimo da ste se odlučili da napravite parser XML-a ili nekog teksta u C++ i vi želite da ekstraktujete samo bitne podatke i da ih zabeležite u JSO notaciji zato što vam je tako lakše da ih ratložite kasnije u Javi kako bi postigli maksimalne performanse. Potrebno je pozvati C++ program i dostaviti mu putanju fajla, pa i da vas parser program obavesti kada je završio

5

SE211 – Domaći zadatak: Java/C++ integracija
tako da Java program može pročitati novonastali fajl ili prihvatila vrednosti direktno. Kako bi ovo uradili moramo napraviti jednostavan interfejs ka komandnoj liniji u Javi.
public void execute(String cmd) { try { String line; Runtime rt = Runtime.getRuntime(); Process p = rt.exec(cmd); BufferedReader input = new BufferedReader (new InputStreamReader(p.getInputStream())); while ((line = input.readLine()) != null) { System.out.println(line); } input.close(); } catch (Exception err) { err.printStackTrace(); } }

Ova jednostavna Javina metoda se može po želji proširiti i usavršiti do željene funkcionalnosti i njome se može izvršiti ma koja komanda na ma kojoj platformi i pratiti njen konzolni output. Na odgovoarajući output pozvanog programa java program bi mogao znati da je program završio ili preko input stream readera učitati ceo output i iskoristiti ga dalje u procesu obrade. Što se tiče C++ pozivanja javinih i drugih programa preko komandne linije, metode za ostvarivanje ovakvih sistemskih poziva su sistemski specifične. U većini slučajeva metoda za kreiranje procesa u C++ je “system(“komanda”)”. Ovo je najlakši i najbrži način integracije ali nije fleksibilan i bezbedan. Kako bi se bezbednost povećala output jednog programa se može enkriptovati kako ga niko drugi ne bi mogao pročitati sem programa koji ga poziva ali to često nije potrebno jer se ovaj pristup primenjuje na jednostavnim rešenjima koja ne zahtevaju zaštitu.

Komunikacija preko mreže
Sledeći logičan način integracije jeste preko mreže. Sam izraz “preko mreže” ne mora da znači da je sistem nužno distribuiran, već i da se koriste protokoli mrežne komunikacije koji rade na jednoj mašini preko loop back mrežnog interfejsa. S ovim rečenim, lako je uvideti prednost mrežne integracije jer se izvršavanje funcionalnih segmenata aplikacije ili sistema može podeliti na više računara koji učestvuju u realizaciji jedne mreže i samim tim se postižu bolje performanse izvršenja i same usluge. Osnovni primer mrežne integracije su brojne klijentskoserverske aplikacije. Server može biti

6

SE211 – Domaći zadatak: Java/C++ integracija
napisan u ma kom jeziku i on nudi neki servis kojim se služe klijenti. Često, pri ovakvom pristupu, uz server stiže i detaljna dokumentacija servisa koji on nudi te je lako razviti klijentske aplikacije koje se ovim serverom služe a koje takođe nisu zavisen od jezika razvoja. Dakle uočavamo još jednu prednost ovakve integracije a to je da nije platformski i jezički zavisna. Ovo je ujedno i najčešći način integracije mada programeri koji je primenjuju često ne svrstavaju to kao integraciju već kao razvoj mrežnih aplikacija. Ali treba imati u vidu da ma koja komunikacija između dva entiteta u cilju nekog zajedničkog produkta jeste integracija.

Soketi
Kada pomenemo mrežnu komunikaciju prvo što nam pada na um jesu soketi. Soket je po definiciji krajna tačka dvosmerne komunikacije nezavisne od protokola na mreži izmrđu dva programa i on je vezan za port određen brojem kako bi Transmission Control Protokol (TCP – protokol kontrole prenosa) transportnog OSI sloja znao kojoj aplikaciji pripadaju podaci. Kada smo vec kod TCP-a potrebno je reći da je komunikacija između soketa preko ovog protokola bazirana na konekciji koja mora biti ostvarena između dva soketa, dok je UDP komunikacija bazirana na P2P, dakle dva klijenta komuniciraju direktno među sobom pa je forma poruke mnogo veća. Posao servera je da sluša zadati port za zahteve konekcija i podatke odgovara na njih istom klijentu ili ih preusmerava na klijente koji moraju da imaju IP adresu servera i da budu prijavljeni na server kako bi se komunikacija izvršila. Na ovaj način se može poslati mnoštvo poruka između dva programa pa je i sama integracija tim putem realizovana. Realizacije soketa u praksi su veoma jednostavne i primeri se mogu nači na mnogo različitih lokacija na internetu, a njihovim poznavanjem možete stvoriti mnoštvo fantastičnih mrežnih aplikacija. Pošto znamo da C++ programi zahtevaju kompajliranje za svaku arhitekturu i znamo da se znatno brže izvršavaju od Javinih pa lako možemo zaključiti da bi u ovom slučaju C++ program bio odličan server. Sledeće parče koda demonstrira jednostavan eho server gde se broj porta propušta kao argument prilikom pozivanja programa (primer: ~$ server 55578):
#include <stdio.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> void error(char *msg) { perror(msg); exit(1); } int main(int argc, char *argv[]) { int sockfd, newsockfd, portno, clilen;

7

SE211 – Domaći zadatak: Java/C++ integracija
char buffer[256]; struct sockaddr_in serv_addr, cli_addr; int n; if (argc < 2) { fprintf(stderr,"ERROR, no port provided\n"); exit(1); } sockfd = socket(AF_INET, SOCK_STREAM, 0); if (sockfd < 0) error("ERROR opening socket"); bzero((char *) &serv_addr, sizeof(serv_addr)); portno = atoi(argv[1]); serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = INADDR_ANY; serv_addr.sin_port = htons(portno); if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) error("ERROR on binding"); listen(sockfd,5); clilen = sizeof(cli_addr); newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen); if (newsockfd < 0) error("ERROR on accept"); bzero(buffer,256); n = read(newsockfd,buffer,255); if (n < 0) error("ERROR reading from socket"); printf("Here is the message: %s\n",buffer); n = write(newsockfd,"I got your message",18); if (n < 0) error("ERROR writing to socket"); return 0; }

8

SE211 – Domaći zadatak: Java/C++ integracija

S druge strane, Java programi su feksibilni i cross platform tako da bi njihova idealna uloga u ovom slučaju bila uloga klijenta:
import java.io.*; import java.net.*; public class EchoClient { public static void main(String[] args) throws IOException { Socket echoSocket = null; PrintWriter out = null; BufferedReader in = null; try { //InetAddress addr = InetAddress.getByName("127.0.0.1"); echoSocket = new Socket("localhost", 55578); out = new PrintWriter(echoSocket.getOutputStream(), true); in = new BufferedReader(new InputStreamReader( echoSocket.getInputStream())); } catch (UnknownHostException e) { System.err.println("Don't know about host: localhost."); System.exit(1); } catch (IOException e) { System.err.println("Couldn't get I/O for " + "the connection to: localhost."); System.exit(1); } BufferedReader stdIn = new BufferedReader( new InputStreamReader(System.in)); String userInput; while ((userInput = stdIn.readLine()) != null) { out.println(userInput); System.out.println("echo: " + in.readLine()); } out.close(); in.close(); stdIn.close(); echoSocket.close(); } }

Pošto razmena po potrebi formatiranih stringova često nije dovoljna, standardima koje je nametnuo W3 Konzilijum, a koji služe za definisanje web servisa, WSDL (Web Service Description Language) mogu se definisati XML forme za prenos raznih sadržaja gde su strukture poruka dobro definisane radi lakšeg čitanja i bolje klasifikacije podataka u okviru jedne poruke. Nastao je i protokol poznatiji kao SOAP (Simple Object Access Protocol) koji se oslanja na XML kako bi omogućio lako kreiranje web servisa. Naravno kako bi se komunikacija između aplikacija zaštitila od tuđih “pogleda” sve poruke je potrebno enkriptovati.

9

SE211 – Domaći zadatak: Java/C++ integracija

Baze podataka
Kolaboracija softvera se može odvijati i preko baza podataka, jer u samom računarstvu više se fokusiramo na obradu podataka u informacije i samim tim alat, u ovom slučaju programski jezik, nije bitan. Tako da bi skup klasifikovanih podataka jedne tipične baze mogao da bude rezultat kolaboracije mnoštva različitog softvera, kao što i različiti softver može vršiti ekstrakciju podataka, obradu i samo prikazivanje informacija nad istim skupom. Razlog zbog koga je ovaj način integracije smešten u komunikaciju preko mreže je to što baza ne mora nužno biti na istom računaru i što se komunikacija s njom uspostavlja preko soketa. Hajde da pogledamo kako se vrši konekcija na MySQL bazu i izvršavaju SQL komande u ova dva jezika našeg interesa. Što se tiče Jave, iako postoje mnogi API-ji i frameworci za komunikaciju s bazama podataka, pozabavićemo se samo JDBC (Java Database Connectivity), u cilju sitacanja osećaja jednostavnosti povezivanja sa bazama podataka. Sledi jednostavan primer konekcije i izvršavanja SQL komande na jednoj lokalnoj bazi:
import java.sql.*; public class MySqlConnect{ public static void main(String[] args) { System.out.println("MySQL Connect Example"); Connection conn = null; String url = "jdbc:mysql://localhost:3306/"; String dbName = "testdb"; String driver = "com.mysql.jdbc.Driver"; String userName = "user"; String password = "pass"; try { Class.forName(driver).newInstance(); conn = DriverManager.getConnection(url+dbName,userName,password); System.out.println("Connected to the database"); try { String sql = "SELECT title,year_made FROM movies WHERE year_made >= 1988 AND year_made <= 2009"; PreparedStatement prest = con.prepareStatement(sql); ResultSet rs = prest.executeQuery(); while (rs.next()) { String mov_name = rs.getString(1); int mov_year = rs.getInt(2); count++; System.out.println(mov_name + "\t" + "- " + mov_year);

10

SE211 – Domaći zadatak: Java/C++ integracija
} System.out.println("Number of records: " + count); prest.close(); conn.close(); System.out.println("Disconnected from database"); } catch (SQLException s) { System.out.println("SQL statement was not executed!"); } } catch (Exception e) { e.printStackTrace(); } } }

I naravno još kraći postupak konekcije i izvršavanja SQL-a u C++:
#include <iostream> #include <mysql.h> //Including mysql heder using namespace std; MYSQL *connection, mysql; int query_state; int main() { cout << "C++ MySQL Example" << endl; mysql_init(&mysql); //connection = mysql_real_connect(&mysql,"host","user","password","database",0,0,0); connection = mysql_real_connect(&mysql,"localhost","user","pass","testdb",0,0,0); if (connection == NULL) { cout << mysql_error(&mysql) << endl; return 1; } cout << "Connected to database" << endl; query_state = mysql_query(connection, "INSERT INTO movies VALUES(Jacobs Ladder,1990)"); if (query_state !=0) { cout << mysql_error(connection) << endl; cout << "SQL statement was not executed!" << endl; return 1; } mysql_close(connection); cout << "Disconnected from database" << endl; return 0; }

11

SE211 – Domaći zadatak: Java/C++ integracija Pošto smo proučili ova dva prosta segmenta koda, uvideli smo da oba programa komunicirati s istom bazom i izvršavati operacije nad istim skupom podataka. Lako je zaključiti efikasnost i fleksibilnost integracije na ovaj način što je i sam razlog široke primene ovakvog pristupa.

CORBA
Common Object Request Broker Architecture, bespotrebno komplikovan baš kao i njegovo puno ime, je standard iz 1991. godine koji omogućuje da softver pisan u različitim jezicima, koji može a ne mora da se izvršava na različitim mašinama, funkcioniše kao jedna aplikacija ili set servisa. Zapravo CORBA normalizuje semantiku za pozivanje metoda između aplikacija koje se izvršavaju u lokalu ili na mreži. Kako bi ovaj sistem radio, od programera se zahteva da proizvede interfejs fajl pomoću IDL (Interface Definition Language) jezika za definisanje interfejsa koji je definisala ista grupa koja razvija CORBA standard, a to je OMG (Object Management Group). Interfejs fajl sadrži informacije o metodama koje želimo da pozivamo iz drugih aplikacija i nakon njegovog definisanja on se mora kompajlirati pomoću IDL kompajlera, koji obično dolazi sa CORBA softverom, i tada se IDL pretvara u kod na jeziku koji se specifira i može se implementirati u aplikaciju. No kako bi dve aplikacije uopšte komunicirale potrebno je postojanje CORBA implementacije, softvera koji će povezivati pozive metoda i omogućiti komunikaciju. CORBA implementacija omogućava instanciranje ORB-a (Object Request Broker) koji komunicira sa drugim ORB-om preko softverske magistrale omogućene protokolima GIOP ili IIOP, dakle ima funkciju middleware-a. Prva i jedina slika u ovom dokumentu, možda najbolje dočarava princip funkcionisanja CORBA specifikacije. Ali kako bi stekli detaljniji uvid o razvoju uz pomoć CORBA specifikacije moramo proći kroz jednostavan praktični primer. Pre svega moramo razlikovati klijentsku od serverske strane. Serverska strana nudi svoje metode i objekte na korišćenje dok ih klijentska strana koristi. Kao što se da zaključiti C++ zbog svoih performansi, niskog nivoa pristupa i biblioteka je pogodan da zauzme stranu servera, dok je Java koja je fleksibilna, cross platform i visokog nivoa logično zauzima stranu klijenta u cilju korišćenja C++ biblioteka i sposobnosti pristupa na hardverskom nivou. Nakon što smo odredili koje će tehnologije zauzeti koju stranu, potrebno je konfigurisati CORBA implementaciju izbora. Ovih implementacija ima mnogo i razvijane su u različitim jezicima, poznate besplatne implementacije za Linux su: OmniORB, TAO, JACrb, MICO, ORBit, Fnorb, a za Windows: ORBacus, ORBit, OpenOrb, VBOrb,

Slika 1: Šematski prikaz principa funkcionisanja CORBA specifikacije 12

SE211 – Domaći zadatak: Java/C++ integracija
opalORB... Treba napisati interfejs IDL fajl koji ćemo koristiti, koji specifira šta će se razmenjivati u komunikaciji. module Counter { interface Count { attribute long sum; long increment(); }; }; Nazovimo ovaj fajl Counter.idl i kompajlirajmo ga IDL kompajlerom za C++ koji smo dobili uz CORBA implementacioni paket. Dobićemo četiri izlazna fajla: Count.h, Count.cpp, Count_skel1.h, Count_skel1.cpp. Count koriste i klijent i server, dok je Count_skel1 samo serverski kostur (Server skeleton) I sadrži samo abstraktnu klasu implementacije objekta. Sledeće što moramo kreirati je Servant (sluga) objekat I on je implementacija objekta koja stvara funkcionalnost kostura koji je definisan IDL-om. Kreiraćemo header fajl servant objekta.
//example of Count i.h #include <OB/CORBA.h> #include "Count_skel.h" #include "iostream.h" // inherit from the Server class Count class Count_i : public POA_Counter::Count public: // constructor Count_i() ; // destructor ~Count_i() ; // get sum value CORBA::Long sum() ; // set sum value void sum(CORBA::Long _itvar_sum) ; // increment sum value CORBA::Long increment() ; private: long The_Sum ; }; {

13

SE211 – Domaći zadatak: Java/C++ integracija

I cpp fajl servant objekta.
//example of Count i.cpp #include "Count_i.h" Count_i::Count_i() { cout << "Created Count object" << endl ; this->The_Sum = 0 ; } Count_i::~Count_i() { cout << "Gone is the Count object" << endl ; } CORBA::Long Count_i::sum() { // get value of sum return this->The_Sum ; } void Count_i::sum(CORBA::Long value) { // set value of sum this->The_Sum = value; } CORBA::Long Count_i::increment() { // increment value of sum by 1 this->The_Sum ++ ; return this->The_Sum ; }

Sada imamo sve potrebno za implementaciju samog servera i evo primera koda:
// example server.cpp #include <OB/CORBA.h> #include <OB/CosNaming.h> #include "Count_i.h" #include <iostream.h> int main( int argc, char **argv) { // initialise the ORB

14

SE211 – Domaći zadatak: Java/C++ integracija
CORBA::ORB_var orb = CORBA::ORB_init(argc, argv); // finding rootPoa CORBA::Object_var poaObject ; PortableServer::POA_var poa ; poaObject = orb->resolve_initial_references("RootPOA"); poa = PortableServer::POA::_narrow(poaObject) ; // Create CORBA object and use it to register // servant object reference with the POA Count_i servant ; poa->activate_object(&servant) ; // Declare naming Context CosNaming::NamingContextExt_var rootCxtExt ; CORBA::Object_var objVarNaming ; // get root NameService objVarNaming = orb->resolve_initial_references("NameService"); rootCxtExt = CosNaming::NamingContextExt::_narrow(objVarNaming) ; // add the count name to the root NameService CosNaming::Name_var name ; name = rootCxtExt->to_name("The counter"); // get object reference CORBA::Object_var c = poa->servant_to_reference(&servant) ; // add object reference to counter rootCxtExt->bind(name, c); // use REbind if the nameservice is already initialized // only use bind the first time you bind an object // rootCxtExt->rebind(name, c); // print IOR of object, just in case... CORBA::String_var str = orb->object_to_string(c); cout << str << "\n" << endl ; cout << "Activating the POA manager.\n" << endl; poa->the_POAManager()->activate() ; orb->run() ; // the ORB will be waiting for requests return 0 ; }

15

SE211 – Domaći zadatak: Java/C++ integracija

Ono što ovo parče koda radi jeste pre svega inicijalizuje ORB na middleware softveru. Ta inicijalizacije zahteva par postupaka a to su da server program: Nalazi referencu ka POA (Portable Object Adapter) koji beleži i vodi računa o kreiranju objekata i njihovom upravljanju. Kreira Servan objekat i vezuje ga za POA. Vezuje ime Servan objekta za imenski servis i on proizvodi IOR objekat (Interoperable Object Reference) koji služi kao medijator prilikom kreiranja novih referenci udaljenih objekata. Zatim POA biva aktiviran i odmah za njim se pokreće ORB. I nakon ovog poprilično kompleksnog procesa možemo krenuti sa kreiranjem klijentske strane u Javi koja će koristiti Counter objekat. Kako bi krenuli sa razvojem koramo pre svega kompajlirati interfejs fajl IDL kompajlerom za javu i to sa argumentom da se ne kreiraju serverski kosturi koji nam ne trebaju: jidl --no-skeletons Count.idl Kao rezultat kompajliranja dobijamo pet fajlova koje uključujemo u klijentski kod a to su: _CountStub.java, Count.java, CountHelper.java, CountHolder.java, CountOperations.java. I to je sve pto nam je potrebno za izradu klijenta Client.java koji izgleda ovako:
import org.omg.CORBA.* ; import org.omg.CosNaming.* ; import java.io.* ; import Counter.* ; public class Client { public static void setOrbacusProperties(java.util.Properties props) throws java.io.FileNotFoundException, java.io.IOException { String javaHome = System.getProperty("java.home"); File propFile = new File("orbacus.properties"); if(!propFile.exists()) propFile = new File(javaHome+File.separator+"lib"+File.separator + "orbacus.properties"); if(!propFile.exists()) System.out.println("Cannot find file: orbacus.properties"); else { FileInputStream fis = new FileInputStream(propFile); System.out.println("Loading "+propFile.getPath()); props.load(fis); fis.close(); } try{ System.out.println("running client..\n"); // load properties for Orbacus, and the location of the NamingService } // end setOrbacusProperties() // importing the compiled idl-code

public static void main(String args[]) {

16

SE211 – Domaći zadatak: Java/C++ integracija
java.util.Properties props = System.getProperties(); setOrbacusProperties(props) ; System.out.println("init ORB.\n"); org.omg.CORBA.ORB orb = org.omg.CORBA.ORB.init(args, props); // connect to nameservice, get IOR of nameservice System.out.println("\n connecting to nameservice...\n"); org.omg.CORBA.Object objNaming = orb.resolve_initial_references("NameService"); NamingContext ncRef = NamingContextHelper.narrow(objNaming); // find object ’The counter’ NameComponent nc = new NameComponent("The counter",""); NameComponent path[] = {nc}; // create a counter object Count counter = CountHelper.narrow(ncRef.resolve(path)); // Set sum to initial value of 0 System.out.println("Setting sum to 0"); counter.sum((int)0); // Calculate Start time long startTime = System.currentTimeMillis(); // Increment 1000 times System.out.println("Incrementing"); for (int i = 0 ; i < 1000 ; i++ ) { counter.increment(); // Calculate stop time; print out statistics long stopTime = System.currentTimeMillis(); System.out.println("Avg = "+ ((stopTime - startTime)/1000f) + " msecs"); System.out.println("Sum = " + counter.sum()); } catch (Exception e) { System.out.println("!Exception...: " + e); } } // end main() } // end class Client }

U koliko pažljivo uporedite priloženi primer sa priloženim blok dijagramom videćete tačno koji od procesa kroz koje smo prošli je obeležen kojim blokom. Kako bi pokrenuli ceo glomazni primer potrebno je samo kompajlirati Server.cpp i Client.java i pokrenuti klijent. Potrebno je još pomenuti da sem podrške za Javu i C++, CORBA specifikacija podržava jezike: Ada, C, Lisp, Ruby, Smaltalk, COBOL, PL/I i Python. Postoji i ne standardna podrška za Perl, VB, Erlang i TCL. Sve u svemu, začin C. Moje lično mišljenje je da CORBA predstavlja kompleksan način integracije jezika bez preke podrebe, jer verovatno cela ta robusnost je predviđena za mnoge druge mogućnosti

17

SE211 – Domaći zadatak: Java/C++ integracija
koje su obećavane od strane OMG a nisu ispunjene te CORBA biva često kritikovana.

Apache Thrift
Pošto smo odali dužno poštovanje staroj tehnici zvanoj CORBA, vreme je da se malo posvetimo savremenim načinima integracije preko mreže. U koliko ste se ikada bavili razvojem web aplikacija, koje iz dana u dan postaju popularnije, verujem da ste se makar jednom zapitali kako je moguće da Facebook (najpopularnija socijalna mreža današnjice) izvlači onako dobre performanse iz PHP-a i kako tako brzo napreduje? Odgovor je jednostavan, to nije samo PHP već novi alat integracije koji su oni razvili i koji im omogućuje da izvuku najbolje iz jezika C++, Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, Smalltalk, Ocaml, smim tim štedeći u vremenu i novcu (prevod reči Thrift je ekonomski menadžment resorsima), a dobijajući fenomenalne performanse. Thrift vuče svoje korene iz CORBA specifikacije I radi na sličnom principu samo, da se pimetiti, mnogo efikasnije i jednostavnije. Sporiji je od RMI (Java Remote Method Invocation) i REST (Representational State Transfer) ali za razliku od njih nudi integraciju različitih jezika i samo na tome se zasniva njegova ekonomičnost. Dakle Thrift je RPC (Remote Procedure Call) framework za razvoj skalabilnih servisa u raznim jezicima. Biblioteka je čista, bez ikakvih konfiguracionih XML fajlova, dok veze s njom izgledaju sasvim skladno u jezicima u koje se implementira. Sve što je potrebno jeste napisati .thrift fajl i kompajlirati ga Thrift kompajlerom za određene jezike koje planirate integrisati. Kompajler automatski generiše sve potrebne fajlove pa i klijentske i serverske kosture koji su spremni za implementaciju. Hajde da razmotrimo sve to kroz jednostavan primer. Osnova svega je .thift fajl jer on služi za definisanje struktura podataka, enumeracionih tipova, konstanti i samog servisa. Thrift fajlovi mogu da imaju namespace I da uključuju druge thrift fajlove, podržavaju klasične shell komentare, duge I kratke C komentare, i sledeće tipove: bool, byte, i16 (šesnaestobitni intidžer), i32, i64, double, string, binary (niz bajtova), map<tip1,tip2>,list<tip>,set<tip>. Naš promer ćemo početi od jednostavnog fajla demo.thrift koji definiše servis sačinjen od jedne funkcije ping.
namespace cpp demo namespace java demo service DemoService { i32 ping() }

Sledeći korak bi bio kompajliranje ovog fajla za jezike C++ i Javu komandama (pod uslovom da je thrift izvršivi fajl u /usr/local/bin/)
thrift --gen cpp demo.thrift thrift --gen java demo.thrift

Kao rezultat komandi dobijamo sledeće fajlove: DemoService.cpp, DemoService.h, DemoService_server.skeleton.cpp, za C++ i DemoService.java, DemoService_server.skeleton.java, za Javu. Sada treba da izaberemo uloge servera I klijenta za izabrane tehnologije. Postupićemi isto kao u CORBA primeru i izabraćemo da C++ uzme ulogu servera a Java ulogu klijenta, dakle ping funkcija će biti pozvana iz Jave, izvršena u C++ i rezultat vraćen u Javu. Pošto je C++ server interesuje nas DemoService_server.skeleton.cpp koji je automatski generisan i izgleda ovako:

18

SE211 – Domaći zadatak: Java/C++ integracija
#include #include #include #include #include using using using using "DemoService.h" <protocol/TBinaryProtocol.h> <server/TSimpleServer.h> <transport/TServerSocket.h> <transport/TTransportUtils.h> apache::thrift; apache::thrift::protocol; apache::thrift::transport; apache::thrift::server;

namespace namespace namespace namespace

using boost::shared_ptr; using namespace demo; class DemoServiceHandler : virtual public DemoServiceIf { public: DemoServiceHandler() { // Your initialization goes here } int32_t ping() { // Your implementation goes here return 15; printf("ping\n"); } }; int main(int argc, char **argv) { int port = 9090; shared_ptr<DemoServiceHandler> handler(new DemoServiceHandler()); shared_ptr<TProcessor> processor(new DemoServiceProcessor(handler)); shared_ptr<TServerTransport> serverTransport(new TServerSocket(port)); shared_ptr<TTransportFactory> transportFactory(new TBufferedTransportFactory()); shared_ptr<TProtocolFactory> protocolFactory(new TBinaryProtocolFactory()); TSimpleServer server(processor, serverTransport, transportFactory, protocolFactory); server.serve(); return 0; }

Ovo parče koda definiše interfejs DemoServiceIf u kome se nalazi hendler servisa i metoda servisa koju smo definisali u .thrift fajlu i kao što vidimo otvara serverski Thrift soket na portu 9090. Fajl treba preimenovati u DemoService_server.cpp kompajlirati i linkovati prilikom čega treba uputiti na Thrift biblioteke i hedere. Java uzima ulogu klijenta pa je fajl na koji obraćamo pažnu DemoService.java koji je takođe autogenerisan i izgleda ovako:

19

SE211 – Domaći zadatak: Java/C++ integracija

package client; import java.net.SocketException; import org.apache.thrift.TException; import org.apache.thrift.protocol.TBinaryProtocol; import org.apache.thrift.protocol.TProtocol; import org.apache.thrift.transport.TSocket; import org.apache.thrift.transport.TTransport; import org.apache.thrift.transport.TTransportException; import demo.*; public class DemoService { private void start(){ TTransport transport; try { transport = new TSocket("localhost", 9090); TProtocol protocol = new TBinaryProtocol(transport);Client client = new Client(protocol); transport.open(); int ping = client.ping(); System.out.println("Ping value:" + ping); transport.close(); } catch (SocketException e) { e.printStackTrace(); } catch (TTransportException e) { e.printStackTrace(); } catch (TException e) { e.printStackTrace(); } } public static void main(String[] args) { DemoService demo = new DemoService(); demo.start(); } }

Nakon kompajliranja program bi trebao da izbaci u sistemski output “Ping value:15” u koliko je server pokrenut. I to je to. Poprilično moćna alatka za integraciju koja je automatizovanija od CORBA specifikacije, bez pisanja dosadnih server objekata i instalacije medijatora, tako da je razvoj u Thriftu znatno brži i samim tim ekonomičniji. Thrift je od skora postao opensource i poklonjen je Apachu na razvoj pa dokumentacija i nije baš najpotpunija. Kvalitetan tutorijal se nalazi u samom Thrift paketu koji možete preuzeti sa sajta i u koliko ste se zaljubili u Thrift tokom ove kratke demosntracije, predlažem da učestvujete u thrift igricama koje hostuje facebook na adresi: http://thriftpuzzle.facebook.com/

20

SE211 – Domaći zadatak: Java/C++ integracija

Sloj interfejsa
Sam pomen interfejsa nas obično asocira na direktan pristup ili komunikaciju. Dakle integracija preko interfejsa bi s te tačke gledišta predstavljala unapred definisane vidove interakcije, u vidu framework-a za komunikaciju, delova programa razvijanih u različitim jezicima.Ovi obično robusni frameworci omogućuju da delovi koda budu veoma lako pozvani i da lako pozivaju delove koda pisanih u drugim jezicima. U nastavku teksta, obratićemo pažnju na četiri popularna framework-a koji se tiču integracije Jave i C++-a, a to su JNI, JNA, SWIG i QTJambi.

Java Native Interface – JNI
Nativni Java Interfejs ili JNI omogućava da Java kod bude pozvan prilikom izvršavanja u Java Virtualnoj mašini od strane nativnih programa niskog nivoa specifičnih za hardver ili operativne sisteme i biblioteka pisanih u C/C++ i Assembly-ju. JNI radi na jednostavnom principu, tako što invokuje nativne funkcije koje su implementirane u posebne .cpp fajlove i propušta JNIEnv pointer i argumente deklarisane od strane Java metode. Prošetajmo kroz jednostavan primer Hello World JNI integracije sa C++: Potrebno je deklarisati nativnu metodu u Javi i to je metoda koju Java želi da probudi i primi njen rezultat. Sadržina HelloWorld.java fajla:
class HelloWorld { private native void print(); public static void main(String[] args) { new HelloWorld().print(); } static { System.loadLibrary("HelloWorld"); } }

HelloWorld.java kompajliramo klasičrno komandom:
javac HelloWorld.java

i napravimo C++ header fajl od HelloWorld prethodno kompajliranog koda komandom
javah -jni HelloWorld

koja kao izlaz daje fajl HelloWorld.h koji sadrži prototip nativne funkcije print
JNIEXPORT void JNICALL Java_HelloWorld_print(JNIEnv *env, jobject obj)

21

SE211 – Domaći zadatak: Java/C++ integracija
Sada zaista pišemo nativnu metodu print u fajlu HelloWorld.cpp:
#include <jni.h> #include <stdio.h> #include "HelloWorld.h" JNIEXPORT void JNICALL Java_HelloWorld_print(JNIEnv *env, jobject obj) { printf("Hello World!\n"); return; }

Kompajliramo klasičnim putem, upućujući na ono što uključujemo i kreiramo biblioteku HelloWorld.so ili HelloWorld.dll u zavisnosti od sistema.Kada god pokrenemo Java program koji smo pisali na početku u sistemskom izlazu će se ispisati ”Hello World”. Veoma jednostavno i jako korisno, zar ne? Ali nepravilno korišćenje JNI može dovesti virtualnu mašinu u nestabilno stanje iz koga se teško stabilizuje tako da se često izbegava. Detaljnija uputstva i specifikacije Java Nativnog Interfejsa možete pročitati u sjajnoj knjizi The Java Native Interface, Programmer's Guide and Specification koju je napisao Sheng Liang i koja se besplatno može skinuti sa Interneta.

Java Native Access – JNA
Java Nativni Pristup omogućava veoma lak pristup bsistemskim bibliotekama i to postiže koristeći libffi (foregin function interface) kako bi dinamično pobudila nativni kod. JNA učitava biblioteke po imenu i povlači pointer neke funkcije iz biblioteke. Proces je potpuno suprotan od JNI, dok je korišćenje još lakše. Sledeći veoma jednostavni primer pokazuje korišćenje osnovne C POSIX

biblioteke i pozivanje standardne funkcije mkdir i rename:
import com.sun.jna.Library; import com.sun.jna.Native; public class exampleOfPOSIX { public interface POSIX extends Library { public int chmod(String filename, int mode); public int chown(String filename, int user, int group); public int rename(String oldpath, String newpath); public int kill(int pid, int signal); public int link(String oldpath, String newpath); public int mkdir(String path, int mode); public int rmdir(String path); } public static void main(String[] args) { POSIX posix = (POSIX) Native.loadLibrary("c", POSIX.class); posix.mkdir("/tmp/newdir", 0777); posix.rename("/tmp/newdir","/tmp/renamedir"); } }

22

SE211 – Domaći zadatak: Java/C++ integracija

Simplified Wrapper and Interface Generator – SWIG
Pojednostavljeni generator omotača i interfejsa, takozvani SWIG, je alat otvorenog koda koji pojednostavljuje povezivanje programa i biblioteka pisanih u C/C++ sa jezicima kao što je Java, C#, Scheme, Ocaml i skripting jezicima poput Tcl, Perl, Python, Ruby, PHP, Lua i R. Potrebno je samo pored C/C++ koda napisati i SWIG interface fajl pomoću koga se generiše interfejs za jedan od navedenih jezika pa se iz tog jezika mogu direktno izvršavati metode kompajliranog C/C++ koda. Razlog je očigledan, jer C/C++ programi su kao što smo ranije spomenuli low level i brzi u izvršavanju ali im nedostaje fleksibilnost i laka mogućnost izmene kao što prđaju navedeni jezici. Često se dešava da ne postoje biblioteke za druge jezike koje su ekvivalentne drevnim i dobro utabanim C/C++ bibliotekama pa ih je pomoću SWIG-a lako integrisati. Kroz primer koji sledi ćemo videti koliko je laka i moćna integracija pomoću SWIG-a. Recimo da imamo C kod koji je napisao naš kolega:
/* File : example.c */ #include <time.h> double My_variable = 3.0; int fact(int n) { if (n <= 1) return 1; else return n*fact(n-1); } int my_mod(int x, int y) { return (x%y); } char *get_time() { time_t ltime; time(&ltime); return ctime(&ltime); }

Pošto se glavni deo programa radi u Javi mi ćemo ga zamoliti da uz svoj C kod priloži i SWIG interfejs fajl kako bi se njegova biblioteka mogla pridružiti ostatku projekta. Ovaj fajl omogućuje SWIGu da zna za koje promenljive i koje metode da generiše interfejs.
/* example.i */ %module example %{ /* Put header files here or function declarations like below */ extern double My_variable; extern int fact(int n); extern int my_mod(int x, int y); extern char *get_time(); %} extern extern extern extern double My_variable; int fact(int n); int my_mod(int x, int y); char *get_time();

23

SE211 – Domaći zadatak: Java/C++ integracija
Pošto smo dobili C biblioteku i SWIG interfejs fajl možemo kreirati interfejs pomoću SWIG-a i kompajlirati kod gcc kompajlerom, što bi u *NIX promptu izgledalo ovako:
$ swig -java example.i $ gcc -c example.c example_wrap.c -I/c/jdk1.3.1/include -I/c/jdk1.3.1/include/win32 $ gcc -shared example.o example_wrap.o -mno-cygwin -Wl,--add-stdcall-alias example.dll

-o

Kada smo to završili možemo pozivati C metode programa koji je priložio naš kolega u našem Java kodu:
public class main { public static void main(String argv[]) { System.loadLibrary("example"); System.out.println(example.getMy_variable()); System.out.println(example.fact(5)); System.out.println(example.get_time()); } }

Kao što se da zaključiti, primena pisanje SWIG interfejsa koje u koliko koliko ste se odlučili baš za SWIG pri naći detaljnu dokumentaciju i http://www.swig.org/Doc1.3/Java.html

SWIG-a znatno olakšava integraciju bez obzira na dodatno se praktikuje uz pisanje koda može postati korisna navika. U integraciji Jave i C++, pogledajte sledeći link na kome možete dodatna uputstva pri integraciji ova dva jezika:

QTJambi
Ovaj način integracije samo govori koliko je QT biblioteka kvalitetan i brz način razvoja grafičkih okruženja. Dovoljno je samo skinuti QT binding biblioteke i importovati ih kako bi omogućili programiranje QT GUI-a direktno iz Jave.
import com.trolltech.qt.gui.*; public class HelloWorld { public static void main(String args[]) { QApplication.initialize(args); QPushButton hello = new QPushButton("Hello World!"); hello.show(); QApplication.exec(); } }

QTJambi je pravi izbor za izradu GUI-a, čak i bolji od Swinga, u koliko poznajete QT, tako da će vaš GUI biti lep i visokih performansi dok ćete ispod imati vaš cross-platform modularni Java backend. Kako bi bolje razumeli prednosti integracije sa QT-om nasuprot Swinga i kako se moje tvrdnje ne bi zasnivale samo na rečima, uzmite sledeći primer u obzir. Swing-ov rukovodioc događaja (Event Handler) :

24

SE211 – Domaći zadatak: Java/C++ integracija
button.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { showDialog(); // code to execute when button is pressed }

});

Isti rukovodioc događaja u QT Jambi-u:
button.clicked.connect(this, "showDialog()");

Ušteda u vremenu izrade je očigledna, no kako bi testirali razliku u performansama moraćete sami da izdvojite vremena i probate ili da mi verujete na reč. Treba takođe naglasiti da jsu prednosti integracije obostrane i da C++ programeri mogu lako svoj QT kod integrisati sa Javom uz QTJambi generator. Nokia je prekinula razvoj QTJambi binding-a Marta 2010. pa je održavanje projekta pripalo open source društvu.

25

SE211 – Domaći zadatak: Java/C++ integracija

Zaključak
Na kraju svakog poglavlja smo zaključili ponešto rezimirajući sjajne tehnike integracije, pa je red da izvedemo globalni zaključak na tu temu. Lično, Thrift mi je ostavio najveći utisak i podsetio me koliko je integracija pravilan postupak prilikom izrade velikih projekata poput facebooka. Facebook razvojni tim se zaista potrudio da izvuče maksimum iz svega kako bi uštedeo I pritom svojim korisnicima, to je ultimativno obostrano zadovoljstvo koje se retko viđa. Pritom, potrudili su se da svoj genijalni alat integracije podele sa svetom i načine ga open source, kažem genijalan bez obzira na to što ta ideja postoji godinama i mnogi drugi razvijaju slične projekte kao što su čuvena CORBA, Protocol Buffers od Googla i Ciskov Etch, jer su se ljudi potrudili da nađu esenciju te ideologije i pretoče je u formu koja je sasvim ugodna za korišćenje. Mislim da su pogodili zlatnu žilu poente integracije i s te tačke gledišta imam puno pravo da im se divim. Zapravo sve te integracije preko mreže su sjajne iz prostog razloga što se ne gubi cross platform epitet Jave, jer se C++ server može udaljiti i izrađivati u poznatom okruženju. Drago mi je što sam načeo ovu temu i stvorio sjajan uvod u mnoge tehnologije o kojima nisam nikada razmišljao, a koje zaslužuju punu pažnju. Ranije sam koristio samo jednostavne i labave načine integracije preko fajla, soketa i baza tako da je ovaj poduhvat predstavljao sjajnu adiciju znanja sopstvenoj kolekciji. Iskreno, jedva čekam da to isto znaje primenim u skorijim projektima. Sledeća tehnika kojom sam bio oduševljen je naravno QT Jambir. Ko se ne bi oduševio programiranju QT-a direktno iz Jave? Nema više pisanja konzolnih Java aplikacija i pozivanja istih iz QT-a direktno iz konzole i parsiranja outputa i fajlova. Jer bez obzira što je starije rešenje fleksibilnije i što za java backend se mogu napisati sjajni frontend GUI u raznim GUI frejmvorcima, bitna je ušteda u vremenu ako se aplikacije razvijaju za poznato okruženje. Pogotovu što obožavam jednostavnost i moć QT-a i svako pisanje GUI-a u njemu mi pričinjava zadovoljstvo. Ostali načini integracije nisu ništa manje sjajni i korisni već naprotiv, baš kao i svaki programski jezik, svaki od njih ima svoju posebnu namenu i kvalitetan je izuzetno pod posebnim okolnostima. Poznavanje istih vam u budućnosti može uštedeti vreme, resorse, novac, ljude, tako da to znanje treba iskotistiti do maksimuma.

26

SE211 – Domaći zadatak: Java/C++ integracija

Sugestije za nastavak rada
Planiram proširiti ovaj dokument tehnikama koje nisam imao vremena pomenuti i možda ga pretvoriti u priručnik za integraciju ma koja dva programska jezika na Srpskom. Takav priručnik bi bio izuzetno koristan prilikom upravljanja velikim projektima koji jednostavno vape za integracijom. U skorijoj budućnoosti ću se fokusirati na razvoj u Thriftu pa možda napišem kvalitetan tutorijal i naravno planiram primenjivati QT Jambi prilikom developement-a za Linux sisteme. Što se tiče razvoja tehnologija integracije, misli mi se roje i možda me navedu na sopstveni pokušaj razvoja sistema koji će pored serversko/klijentskog pristupa podržavati i middle-ware software koji će služiti kao bazen sa linkerima za servise koji nude server programi i kojima će moći mnoštvo klijenata da se priključi nezavisno od jezika naravno. Mada rešenje zvuči kao CORBA, smatram da bi se moglo mnogo lakše i elegantnije izvesti.

27

SE211 – Domaći zadatak: Java/C++ integracija

Literatura
Java vs. C++ - http://verify.stanford.edu/uli/java_cpp.html Java and C++ A critical comparison - Robert C. Martin Comparison of Java and C++ - http://en.wikipedia.org/wiki/Comparison_of_Java_and_C%2B%2B Using Runtime.exec() - http://www.rgagnon.com/javadetails/java-0014.html When Runtime.exec() won't - Michael C. Daconta - http://www.javaworld.com/javaworld/jw-12-2000/jw-1229traps.html I/O from command line – The Java Tutorials - http://download-llnw.oracle.com/javase/tutorial/essential/io/cl.html Calling an external program in C (Linux) - http://www.gidforums.com/t-3369.html Starting processes C/C++ - http://www.codeguru.com/forum/showthread.php?t=302501 on Thinking on Java – Bruce Eckel Core Java 2 – Horstmann Cornell C++ in a nutshell – Ray Lischner All about sockets – The Java Tutorials - http://downloadllnw.oracle.com/javase/tutorial/networking/sockets/index.html C++ Socket Tutorial - http://www.linuxhowtos.org/C_C++/socket.htm Using a MySQL Database with C++ - http://cprogramming.suite101.com/article.cfm/using_a_mysql_databases_with_c Practical tutorial for using Corba – Jan van Gemert Introduction to CORBA - http://java.sun.com/developer/onlineTraining/corba/corba.html CORBA - http://en.wikipedia.org/wiki/Common_Object_Request_Broker_Architecture CORBA - http://www.yourdictionary.com/computer/corba Documents Associated with CORBA 3.1 - http://www.omg.org/spec/CORBA/3.1/ What is CORBA? - http://www-cdfonline.fnal.gov/daq/CORBAXXX/tutorial.html Apache Thrift Wiki - http://wiki.apache.org/thrift/ Apache Thrift - http://newitfarmer.com/bbs/simple/?t19852.html

The Java Native Interface, Programmer's Guide and Specification – Sheng Liang
Java Native Access - http://en.wikipedia.org/wiki/Java_Native_Access JNA - https://jna.dev.java.net/ SWIG - http://en.wikipedia.org/wiki/SWIG SWIG Tutorial - http://www.swig.org/tutorial.html SWIG and Java - http://www.swig.org/Doc1.3/Java.html QT Jambi - http://en.wikipedia.org/wiki/Qt_Jambi Java desktop developement with QT Jambi - http://www.javaworld.com/javaworld/jw-08-2007/jw-08-qtjambi.html

28

Sign up to vote on this title
UsefulNot useful