2011-01-12 38 views
12

Tôi phát triển các ứng dụng/chương trình trong C/C++. Tôi thông thạo hơn hai ngôn ngữ này và yêu thích trở thành nhà phát triển C++. Tôi tự hỏi làm thế nào để tạo ra một chương trình Java có chứa tất cả các mã C + + của tôi.Gói C/C++ trong Java

Ý tôi là, tôi muốn bọc tất cả mã C++ (đã được phát triển) trong lớp Java. Nhưng không biết làm thế nào để làm điều đó.

Vui lòng đăng câu trả lời hoặc các phương pháp/bước của bạn để tích hợp C++ trong Java. (sử dụng JNI là cách, nhưng tôi không thể tìm ra trên www cách sử dụng nó)

FYI, tôi sử dụng IDE Eclipse để phát triển.

Tôi nên bao gồm gói và gói nào trong vùng làm việc dự án của mình?

+0

Vấn đề chung của bạn không thể dễ dàng được giải quyết; chuyển đổi từng lớp C++ một lần vào các lớp Java thông qua JNI là khá khó khăn. Tại sao bạn muốn sử dụng các lớp C++ này trong Java? Có lý do nào bạn phải sử dụng Java nhưng muốn có chức năng hiện tại? – templatetypedef

+0

Tôi không muốn mất chức năng của C++. Nó thực hiện một số chức năng mà Java không thể tự làm và tôi không biết làm thế nào để làm tất cả mọi thứ trong Java. Vì vậy, tôi muốn tích hợp C++ của tôi bên trong Java. :-) :-) –

+3

"... Nó thực hiện một số chức năng mà Java không thể tự làm ..." - Tôi xin chân thành hỏi câu này. "Không thể làm"? Bằng chứng, xin vui lòng. – duffymo

Trả lời

7

Nếu bạn muốn gọi C++ từ Java, bạn sẽ cần sử dụng JNI - Giao diện nguyên gốc Java.

Được cảnh báo rằng bạn mất một số lợi ích của bộ thu gom rác, vì nó không thể xử lý các đối tượng C++ của bạn và mã của bạn sẽ không thể di chuyển được nữa.

Có thể bạn sẽ được phục vụ tốt hơn bằng cách học viết 100% Java và để lại C++ phía sau, nhưng đó chỉ là một gợi ý.

+1

Tôi có mọi thứ sẵn sàng trong C++ để thu thập rác từ tất cả các phần của mã. Tôi sẽ cảm thấy tuyệt vời cho bạn nếu bạn có thể gửi cho tôi một ví dụ tối thiểu về việc sử dụng JNI. :-) –

+0

Đó là những gì các hướng dẫn trong liên kết là cho. – duffymo

+0

Sẽ dùng thử. Cảm ơn! –

0

Mô-đun JNI không phải là một lớp Java. Đó là C. Sử dụng JNI có nhiều hạn chế và một số môi trường Java không hỗ trợ tốt JNI.

Không có hỗ trợ cách "quấn C của tôi ++ mã bên trong lớp Java" (EDIT: Tôi có nghĩa là, không JNI noway nhưng JNI là có vấn đề.)

Bạn có thể tra tùy chỉnh C++ biên dịch phát ra Java mã byte , nhưng không ai (bao gồm tôi) sẽ giới thiệu phương pháp này.

3

Có rất nhiều hướng dẫn để thực hiện chính xác những gì bạn muốn làm. Ví dụ: hãy xem: http://www.javamex.com/tutorials/jni/getting_started.shtml

Ngoài ra còn có nhiều cảnh báo sử dụng JNI. Gần đây tôi đã bắt đầu làm việc với nó (chỉ để cho vui, thực sự), và nó có xu hướng vui hơn rất nhiều so với tôi đã dự đoán trước.

Trước hết, bạn phải đối phó với mã khó hiểu như:

#include "test_Test.h" 

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

Thứ hai, nó có xu hướng hạ thấp vai trò một trong những lý do chính tại sao bạn sử dụng Java ở nơi đầu tiên: Wora (Viết Một lần, Run Anywhere). Như duffymo đã đề cập, cũng có thể có vấn đề với bộ thu gom rác, nhưng tôi nghĩ rằng trong những năm gần đây, JVM đã khá thông minh về tích hợp JNI.

Với điều đó đã nói, để chuyển tất cả mã C++ của bạn sang JNI, bạn cần phải cấu trúc lại giao diện của mình (và thậm chí có thể thực hiện một số thể dục dụng cụ bên trong). Nó không phải là không thể, nhưng nó thực sự không được khuyến khích. Giải pháp lý tưởng chỉ là viết lại mã của bạn bằng Java.

Với điều đó đã nói, bạn cũng có thể "chuyển đổi" mã của bạn từ C/C++ thành Java theo chương trình, và có rất nhiều tiện ích như vậy. Nhưng, tất nhiên, máy móc có nhiều gỗ hơn mọi người và chúng cũng bị ràng buộc phạm sai lầm, tùy thuộc vào mức độ phức tạp của lớp học của bạn.

+0

Bạn đã cho nó tuyệt vời! Sẽ cố gắng này vào cuối tuần! –

5

Bạn không thể "chỉ quấn nó", bạn phải viết một số keo C/C++.

Để bắt đầu, SWIG có thể thực hiện hầu hết các công việc cho bạn.

+0

SWIG là tốt đẹp nếu bạn muốn viết nhiều ràng buộc giữa nhiều ngôn ngữ. Viết ánh xạ một lần và chỉ tạo cổng. Nhưng nó vẫn còn quá nhiều công việc để xác định lại tất cả các cấu trúc dữ liệu để ánh xạ mọi thứ ngay cả trong SWIG. Nó tốt hơn là viết JNI. Nhưng có những lựa chọn thay thế tốt hơn ala JNA. – chubbsondubs

1

Tôi sẽ tránh JNI vì nó tẻ nhạt để viết, tiết, và chỉ là một nỗi đau hoàn toàn. Thay vào đó tôi muốn sử dụng thư viện JNA mà làm cho việc viết tích hợp bản địa rất đơn giản.

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

Chúc may mắn.

0

BridJ được thiết kế với mục đích cho điều đó (và được hỗ trợ bởi JNAerator, sẽ phân tích cú pháp tiêu đề C/C++ của bạn và nhổ ra các ràng buộc Java cho bạn).

Đây là giải pháp thay thế gần đây cho JNA, với hỗ trợ cho C++.

13

Thay vì JNI, hoặc JNI với một số hỗ trợ từ một máy phát wrapper tự động như SWIG, hoặc thậm chí JNA, bạn có thể xem xét tách C/C++ và Java vào các quá trình riêng biệt và sử dụng một số hình thức của IPC và/hoặc Java Process trừu tượng để gọi đến một chương trình được viết bằng C/C++. Cách tiếp cận này từ bỏ "gói", vì vậy trong một số ý nghĩa nó không phải là một câu trả lời cho câu hỏi này, nhưng xin vui lòng đọc trên trước khi bỏ phiếu xuống. Tôi tin rằng đây là một câu trả lời hợp lý cho vấn đề rộng hơn trong một số trường hợp.

Lý do cho cách tiếp cận này là khi bạn gọi C/C++ trực tiếp từ Java, JVM có nguy cơ bị lỗi trong mã gốc. Nguy cơ phụ thuộc phần nào vào số lượng mã gốc là của bạn và số tiền bạn liên kết với mã của bên thứ ba (và số lượng quyền truy cập bạn có vào mã nguồn của mã bên thứ ba đó).

Tôi đã gặp phải tình huống mà tôi phải gọi thư viện C/C++ từ Java và thư viện C/C++ có lỗi khiến JVM gặp sự cố. Tôi không có mã nguồn của bên thứ ba, vì vậy tôi không thể sửa (các) lỗi trong mã gốc. Giải pháp cuối cùng là gọi một chương trình C/C++ riêng biệt, được liên kết với thư viện của bên thứ ba. Ứng dụng Java sau đó thực hiện các cuộc gọi đến nhiều quá trình tự nhiên bất thường bất cứ khi nào nó cần thiết để gọi các công cụ C/C++.

Nếu mã gốc có sự cố, bạn có thể khôi phục/thử lại trong Java. Nếu mã nguồn gốc được bọc và gọi từ quá trình JVM, nó có thể lấy toàn bộ JVM.

Cách tiếp cận này có tác động tiêu thụ hiệu suất/tài nguyên và có thể không phù hợp với ứng dụng của bạn, nhưng đáng xem xét trong một số trường hợp nhất định.

Có một ứng dụng riêng biệt thực hiện chức năng của mã C/C++ có khả năng hữu ích như một tiện ích độc lập và để thử nghiệm. Và có một số giao diện dòng lệnh hoặc IPC sạch sẽ có thể làm giảm tích hợp trong tương lai với các ngôn ngữ khác.

Là một giải pháp thay thế khác, bạn có thể tham gia native signal handling để giảm thiểu rủi ro cho tính toàn vẹn của quy trình JVM nếu bạn thích và gắn bó với giải pháp bao gói.

+0

Cảm ơn câu trả lời của bạn. Vâng, kỹ năng kiến ​​trúc của tôi không phải là tốt .. Nhưng tôi phải viết các ứng dụng như bạn đã đề cập (tách chúng thành 2 quy trình), tôi phải xem xét lời khuyên này. Sẽ mất thời gian cho tôi để lấy lại cho bạn với vài câu hỏi. Cảm ơn, một lần nữa .. –

1

Bạn có thể viết mã C++ qua JNI nhưng không có ánh xạ trực tiếp từ các lớp C++ đến các lớp Java. Tôi đã sử dụng JNI để khắc phục các sự cố được tìm thấy trong SDK Android (cụ thể là việc triển khai FloatBuffer.put cực kỳ chậm) và tôi có thể sử dụng nó cho một số lĩnh vực hoạt động quan trọng. Lời khuyên của tôi sẽ là sử dụng nó một cách tiết kiệm và trong một con vịt, thực hiện các công cụ quan trọng và để lại, mà không cần phân bổ bộ nhớ nếu bạn có thể giúp nó. Ngoài ra, đừng quên đo lường mã của bạn để xem mã có thực sự là nhanh hơn hay không.

Không quan tâm, bạn đang phát triển nền tảng nào? Nền tảng duy nhất mà nó sẽ có ý nghĩa để bọc rất nhiều mã C++ trong một lớp java ánh sáng sẽ là Android - trên các nền tảng khác, chỉ biên dịch trong C++ và đã thực hiện với nó.