2010-03-05 42 views
32

Tôi cần gọi some methods in Wininet.dll từ một chương trình Java.Gọi phương thức Win32 API từ Java

Tôi có thể tìm thấy nhiều hướng dẫn về cách gọi một DLL mới mà tôi tạo từ Java, nhưng tôi dường như không tìm thấy bất kỳ hướng dẫn nào về cách gọi một DLL đã tồn tại từ Java.

Tôi biết điều này liên quan đến JNI, nhưng làm thế nào, chính xác, tôi có làm điều này không? Tôi có cần gọi số javah trên Wininet.h không? Tôi lấy một bản sao của Wininet.h ở đâu? Một con trỏ tới một hướng dẫn chi tiết hiện có là sẽ là đủ.

Trả lời

38
  1. JNA dường như the industry standard những gì bạn muốn, "cung cấp các chương trình Java dễ dàng truy cập vào các thư viện chia sẻ nguồn gốc (DLL trên Windows) mà không viết bất cứ điều gì nhưng mã Java-no JNI hoặc mẹ đẻ đang yêu cầu"

  2. Ngoài ra còn có Java Foreign Function Interface - example usage
    Nếu là ok fo r bạn, bạn có thể embed các JRuby thông dịch viên và gọi WINAPI qua jruby-ffi mà là dễ dàng hơn nhiều, xem here, here, và here

+2

nhu cầu này Một vết sưng - JNA tốt hơn nhiều so với JNI thuần túy để truy cập thư viện gốc –

+0

+1: JNA là lựa chọn tốt Mặc dù, bạn cần tìm ra cách ánh xạ chữ ký hàm trong Java. Gần đây tôi đã sử dụng JNA để giao tiếp với một bluetooth thiết bị thông qua API Win32 bản địa – wierob

+0

JNA thực sự là trơn tru Khi tôi giải thích nó cho một người bạn tại nơi làm việc trong tuần khác, tôi thực sự đã đi xa đến mức để nói với anh ta đó là "ma thuật". – rob

3

Không thể gọi trực tiếp thư viện gốc: điều này là do một số đối số trong phương thức không được hỗ trợ bởi Giao diện bản địa Java.

Có một cái gì đó gọi là GlueGen, điều này sẽ tạo ra một nhị phân riêng biệt mà sẽ tự động liên kết với DLL gốc của bạn. Các nhị phân được tạo ra tương thích với JNI và do đó có thể gọi từ Java.

http://en.wikipedia.org/wiki/Gluegen

Để có được một tiêu đề-file cho wininet.dll, có lẽ bạn cần phải có nền tảng SDK (hoặc Windows SDK, phiên bản mới nhất). Bạn cũng có thể tìm kiếm trên mạng cho một kho lưu trữ trực tuyến có chứa tệp tiêu đề này.

GlueGen sẽ cần một tiêu đề-file, một trình biên dịch C ANSI vv

Ngoài ra còn có một thư viện ít được biết đến gọi NativeCall, mà không yêu cầu GlueGen. Nó đã có các tệp nhị phân tương thích với Java. Điều này rõ ràng là chậm hơn, vì nó sẽ tải DLL động theo yêu cầu từ Java. Tôi đã không được sử dụng này, tuy nhiên, nhưng nó có vẻ đầy hứa hẹn:

http://johannburkard.de/software/nativecall/

12

tôi phải làm điều này một thời gian ngắn trước đây. Bạn sẽ cần một trình biên dịch C và các tệp tiêu đề Windows. Tôi đã sử dụng mingw vì nó miễn phí và tôi chỉ biên soạn một tập tin nhỏ.

Trước tiên, bạn tạo lớp học. Dưới đây là ví dụ:

package org.whatever.thingy; 

public class MyClass { 
    // Here is a JNI method, identified by 'native' 

    public static native callWin32Thingy(int x, int y, boolean z); 

    /* At this point, normal class stuff, other methods, variables, whatever */ 
} 

Sau đó, bạn sử dụng một trong các lệnh đi kèm trong JDK, sẽ tự động lấy lớp của bạn và tạo tệp .h và .c. Lệnh này là "javah". Chữ ký của phương thức sẽ trông giống như sau:

JNIEXPORT void JNICALL Java_com_whatever_1thingy_MyClass_callWin32Thingy 
    (JNIEnv *, jclass, jint, jint, jboolean); 

Trong tệp .c, bạn bao gồm bất kỳ tiêu đề cửa sổ nào bạn cần và xác định phương pháp.

JNIEXPORT void JNICALL Java_com_whatever_1thingy_MyClass_callWin32Thingy 
    (JNIEnv *a, jclass b, jint c, jint d, jboolean e) { 
    // Prep steps.... 

    Win32MethodCallWeCareAbout(x, y, z, hWhatever); 

    // Cleanup stuff... 
} 

Đó là rất quan trọng bạn không đổi tên phương pháp, đó là cách nó được kết hợp với lớp học cụ thể của bạn.

Khi bạn đã có điều đó, bạn biên dịch các tệp đó thành một tệp DLL. Dưới đây là các lệnh tôi đã sử dụng cho mingw, bạn sẽ phải điều chỉnh các lớp/đường dẫn/etc.

c:/MinGW/bin/gcc -c -Ic:/MinGW/include -I"c:/Program Files/Java/jdk1.5.0_12/include" 
    -I"c:/Program Files/Java/jdk1.5.0_12/include/win32" -D__int64="long long" 
    com_whatever_thingy_MyClass_JNIHelper.c 

c:/MinGW/bin/gcc -shared -o JNIHelper.dll 
    com_whatever_thingy_MyClass_JNIHelper_JNIHelper.o 
    -Wl,--add-stdcall-alias,--kill-at,--output-def,def_file 

Điều này sẽ tạo một số tệp, bao gồm JNIHelper.dll, tên tôi đã đặt tên là DLL của tôi.

Tại thời điểm này, về cơ bản bạn đã hoàn tất. Bạn sử dụng lớp Java của bạn như bình thường, và nó sẽ chạy mã Win32 của bạn khi bạn gọi phương thức tĩnh. Tất cả những gì bạn phải làm là nhập thư viện. Một nơi nào đó trong mã của bạn (tôi đặt nó trong một khối tĩnh trong lớp học của tôi), bạn sẽ cần dòng này:

System.loadLibrary("JNIHelper"); 

Điều này sẽ gây Java để tải các thư viện có tên là "JNIHelper.dll" và liên kết nó vào mã . Nó phải ở đâu đó trong đường dẫn thư viện mà Java biết.

Vậy đó. Đó là một loạt các boilerplate, nhưng nếu bạn đang làm một số gói đơn giản, thật dễ dàng. Nếu bạn phải đối phó với các loại Java hoặc cấp phát bộ nhớ, nó trở nên tồi tệ hơn (lưu ý: tôi đã không, vì vậy tôi không có kinh nghiệm ở đó).

Có cả một hướng dẫn here (lần đầu tiên tôi thấy ngày hôm nay rằng trông đàng hoàng, và bạn có thể tìm thấy những người khác trên web. Các bài viết Wikipedia trên JNI có biết thêm quá.

Hope this helps.

+1

Bạn không cần từ khóa "tự nhiên" trong lớp Java của mình? –

+0

@ Thorbjørn: Quyền của bạn, tôi đã bỏ lỡ điều đó, cảm ơn. Đã chỉnh sửa để thêm. – MBCook

Các vấn đề liên quan