2011-01-12 18 views
12

Rozwijam aplikacje/programy w C/C++. Jestem bardziej obeznany w tych dwóch językach i uwielbiam być deweloperem C++. Zastanawiam się, jak utworzyć program Java, który zawiera cały mój kod C++.Zawijanie C/C++ wewnątrz Javy

To znaczy, chciałbym zawinąć cały mój kod C++ (który jest już opracowany) w klasie Java. Ale nie wiem jak to zrobić.

Prosimy o umieszczanie odpowiedzi lub metod/kroków na integrację C++ w Javie. (używanie JNI to sposób, ale nie mogłem go rozgryźć na stronie internetowej, jak go użyć)

FYI, używam Eclipse IDE do opracowania.

Jak i jakie pakiety należy dołączyć do obszaru roboczego projektu?

+0

Twój ogólny problem nie może być łatwo rozwiązany; Konwersja każdej klasy C++ pojedynczo na klasy Java poprzez JNI jest dość trudna. Dlaczego chcesz używać tych klas C++ w Javie? Czy jest jakiś powód, dla którego musisz używać Javy, ale chcesz istniejącej funkcjonalności? – templatetypedef

+0

Nie chcę stracić funkcjonalności mojego C++. Wykonuje pewne funkcje, których Java nie może wykonywać samodzielnie i nie wiem jak to zrobić w Javie. Chciałbym zintegrować moje C++ w Javie. :-) :-) –

+3

"... Wykonuje pewne funkcje, których Java nie może wykonywać samodzielnie ..." - Szczerze podważam to stwierdzenie. "Nie mogę zrobić"? Dowody, proszę. – duffymo

Odpowiedz

7

Jeśli chcesz wywołać C++ z Javy, musisz użyć JNI - Java Native Interface.

Ostrzegam, że tracisz niektóre zalety śmieciarza, ponieważ nie może on zajmować się obiektami C++, a Twój kod nie będzie już przenośny.

Może lepiej poradzisz sobie z nauką pisania w 100% Java i pozostawianiem C++, ale to tylko sugestia.

+1

Mam wszystko gotowe w moim C++ do zbierania śmieci ze wszystkich części kodu. Czułbym się świetnie, gdybyś mógł podać mi minimalny przykład używania JNI. :-) –

+0

Do tego służy samouczek w linku. – duffymo

+0

Spróbuję. Dzięki! –

0

Moduł JNI nie jest klasą Java. To C. Używanie JNI wiąże się z wieloma ograniczeniami, a niektóre środowiska Java nie obsługują dobrze JNI.

Nie ma obsługiwane sposób „wrap mojego kodu C++ wewnątrz klasy Java” (EDIT: To znaczy, bez JNI bynajmniej ale JNI jest problematyczne.)

Można zbadać niestandardowe kompilator C++ emitują Java kodów bajtowych , ale nikt (włączając mnie) nie poleci tego podejścia.

3

Istnieje wiele samouczków do robienia dokładnie tego, co chcesz robić. Na przykład sprawdź: http://www.javamex.com/tutorials/jni/getting_started.shtml

Istnieje również wiele zastrzeżeń dotyczących używania JNI. Niedawno zacząłem z nim pracować (po prostu dla zabawy, naprawdę), i wydaje się być o wiele mniej zabawny, niż początkowo przewidywałem.

Przede wszystkim, masz do czynienia z kodem tajemnicze, takie jak:

#include "test_Test.h" 

JNIEXPORT jint JNICALL Java_test_Test_getDoubled(JNIEnv *env, jclass clz, jint n) { 
    return n * 2; 
} 

drugie, ma ona tendencję do bagatelizowania jeden z głównych powodów, dla których używasz Java w pierwszej kolejności: wora (Write Raz, Run Anywhere). Jak wspomniałem w duffymo, mogą być również problemy z śmieciarzem, ale myślę, że w ostatnich latach JVM nabrała dość sprytnego spojrzenia na integrację JNI.

Powiedziawszy to, aby przesłać cały kod C++ do JNI, musisz zmienić swoje interfejsy (a może nawet wykonać pewne wewnętrzne ćwiczenia gimnastyczne). Nie jest to niemożliwe, ale naprawdę nie jest zalecane. Idealnym rozwiązaniem jest ponowne napisanie kodu w Javie.

Mając to na uwadze, można również "przekonwertować" swój kod z C/C++ na język Java programowo, a istnieje mnóstwo takich narzędzi. Ale, oczywiście, maszyny są głupsze niż ludzie i są również zobowiązani do popełniania błędów, w zależności od tego, jak skomplikowana jest twoja klasa.

+0

Dałeś to niesamowite! Spróbuję tego w weekend! –

5

Nie można "po prostu owinąć", trzeba napisać klej C/C++.

Na początek, SWIG może zrobić większość prac dla Ciebie.

+0

SWIG jest fajny, jeśli chcesz pisać wiele powiązań między kilkoma językami. Napisz mapowanie raz i po prostu wygeneruj porty. Ale wciąż jest za dużo pracy, aby na nowo zdefiniować wszystkie struktury danych, aby mapować wszystko nawet w SWIG. To lepsze niż pisanie JNI. Ale są lepsze alternatywy, takie jak JNA. – chubbsondubs

1

chciałbym uniknąć JNI bo to nudne pisać, gadatliwy, i po prostu całkowicie ból. Zamiast tego użyłbym biblioteki JNA, która sprawia, że ​​pisanie natywnej integracji jest tak proste.

https://github.com/twall/jna/

Powodzenia.

0

BridJ został zaprojektowany specjalnie do tego celu (i jest obsługiwany przez JNAerator, który przeanalizuje nagłówki C/C++ i wypluje dla ciebie wiązania Java).

Jest to ostatnia alternatywa dla JNA, ze wsparciem dla C++.

13

Zamiast JNI lub JNI niektóre pomoc z automatycznym generatorem owijarki jak SWIG lub nawet JNA, można rozważyć oddzielenie C/C++ i Java w oddzielnych procesach i za pomocą jakiejś formy IPC i/lub Java Process abstrakcja do wywołania programu napisanego w języku C/C++. Takie podejście porzuca "pakowanie", więc w pewnym sensie nie jest to odpowiedź na to pytanie, ale proszę przeczytać je przed głosowaniem w dół. Uważam, że jest to rozsądna odpowiedź na szerszy problem w niektórych przypadkach.

Powodem takiego podejścia jest to, że podczas wywoływania C/C++ bezpośrednio z Java, , JVM narażona jest na każdy błąd w kodzie macierzystym. Ryzyko zależy w pewnym stopniu od tego, ile kodu natywnego jest twoje i od tego, ile linkujesz do kodu strony trzeciej (i ile masz dostępu do kodu źródłowego takiego kodu strony trzeciej).

Zabrakło mi w sytuacji, gdzie musiałem zadzwonić do C/C++ biblioteki z Java i C/C++ biblioteka miała błędy, które spowodowały awarię JVM. Nie miałem kodu źródłowego strony trzeciej, więc nie mogłem naprawić błędów w natywnym kodzie. Ostatecznie rozwiązaniem było wywołanie osobnego programu C/C++, połączonego z biblioteką strony trzeciej. Aplikacja Java następnie wywoływała wywołania wielu efemerycznych procesów natywnych za każdym razem, gdy trzeba było wywoływać elementy C/C++.

Jeśli natywny kod ma problem, może być w stanie odzyskać/ponów w Javie. Jeśli kod natywny jest zawijany i wywoływany z procesu JVM, może on zniszczyć całą maszynę JVM.

To podejście ma wpływ na wydajność/zużycie zasobów i może nie być odpowiednie dla aplikacji, ale warto rozważyć w niektórych sytuacjach.

Posiadanie osobnej aplikacji, która sprawdza funkcjonalność kodu C/C++, może być użyteczne jako samodzielne narzędzie i do testowania. A posiadanie jakiegoś prostego interfejsu wiersza poleceń lub IPC może ułatwić przyszłe integracje z innymi językami.

Jako inną alternatywę można uzyskać native signal handling w celu zmniejszenia ryzyka dla integralności procesu JVM, jeśli użytkownik lubi i pozostanie przy rozwiązaniu do pakowania.

+0

Dzięki za odpowiedź. Cóż, moje umiejętności architektoniczne nie są takie dobre ... Ale muszę napisać aplikację, jak wspomniałeś (oddzielić je do 2 procesów), muszę rozważyć tę radę. Będę potrzebował czasu, bym wrócił do ciebie z kilkoma pytaniami. Dzięki jeszcze raz.. –

1

Możesz napisać kod C++ przez JNI, ale nie ma bezpośredniego mapowania z klas C++ na klasy Java. Użyłem JNI aby rozwiązać problemy występujące w Android SDK (konkretnie niezwykle powolnego wdrażania FloatBuffer.put) i mogę skończyć używając go na niektórych obszarach krytycznych wydajności. Moja rada będzie polegać na oszczędnym używaniu go i opuszczaniu, bez wykonywania jakiejkolwiek alokacji pamięci, jeśli możesz w tym pomóc. Nie zapomnij również zmierzyć kodu, aby przekonać się, czy naprawdę jest to szybsze od.

Ciekawe, na jakiej platformie pracujesz? Jedyną platformą, w której byłoby sensownym zawinięcie dużej ilości kodu C++ w jasnej warstwie Javy, byłby Android - na innych platformach, po prostu kompilował się w C++ i zrobił to z nim.