C++ и Java: совместное использование - JNI функции
ОГЛАВЛЕНИЕ
JNI функции
JNI определяет 210 прикладных функций. Доступ к ним из С/С++-функции можно получить через интерфейсный указатель JNIENV*, который передается каждой С/С++-функции, представлющей реализацию собственного метода. Все функции разделены на 14 групп:
- информация о версии JNI;
- операции с классами;
- исключения (EXCEPTIONS);
- обработка глобальных и локальных ссылок;
- операции с объектами;
- доступ к данным объекта;
- вызов методов объекта (INSTANCE METHOD);
- доступ к статическим данным объекта;
- вызов методов класса (CLASS METHOD);
- операции со строковыми объектами;
- операции с массивами;
- регистрация собственных методов;
- операции с мониторами (MONITOR OPERATIONS);
- интерфейс с JVM.
Использование JNI функций необходимо только в том случае, если С/С++-функция осуществляет какое-либо взаимодействие с JVM: вызов JAVA-методов, доступ к данным, создание JAVA-объектов и т.д.
Ниже приведен пример JAVA-программы, которая выводит на печать количество свободной памяти на диске С для платформы WIN32. Для этого используется собственный метод и соответствующая реализационная С/С++-функция, вызывающая при своей работе функцию WIN32 API.
// Файл APP.JAVA
PUBLIC CLASS APP {
PUBLIC STATIC VOID MAIN(STRING ARGS[]) {
SYSTEMSPECIFIC SS = NEW SYSTEMSPECIFIC();
TRY {
LONG BYTES = SS.GETCDRIVEFREESPACE();
IF (BYTES != -1) {
LONG KB = BYTES / 1024;
SYSTEM.OUT.PRINTLN("на диске C:\\ свободно " + KB + " KB");
}
ELSE {
SYSTEM.OUT.PRINTLN("произошла ошибка в С/С++-функции");
}
}
CATCH (UNSATISFIEDLINKERROR E) {
SYSTEM.OUT.PRINTLN("метод не найден (" + E + ")");
}
}
}
CLASS SYSTEMSPECIFIC {
STATIC {
TRY {
SYSTEM.LOADLIBRARY("SYSSPEC");
}
CATCH (UNSATISFIEDLINKERROR E) {
SYSTEM.OUT.PRINTLN("библиотека не найдена (" + E + ")");
}
}
NATIVE LONG GETCDRIVEFREESPACE();
}
// Файл SYSTEMSPECIFIC.CPP
#INCLUDE "SYSTEMSPECIFIC.H"
#INCLUDE <WINDOWS.H>
JNIEXPORT JLONG JNICALL JAVA_SYSTEMSPECIFIC_GETCDRIVEFREESPACE (JNIENV *, JOBJECT) {
DWORD SCTRPERCLSTR, BYTESPERSCTR, FREECLSTR, CLSTR;
BOOL RES = GETDISKFREESPACE("C:\\", &SCTRPERCLSTR, &BYTESPERSCTR, &FREECLSTR, &CLSTR);
RETURN RES == TRUE ? SCTRPERCLSTR * BYTESPERSCTR * FREECLSTR : -1;
}
Для успешной компиляции кода JAVA и С/С++ на платформе WIN32 необходимо правильно установить переменные окружения PATH, LIB, INCLUDE и CLASSPATH (многие из этих значений можно задать как параметры соответствующих компиляторов).
Если записать исходные тексты предыдущего примера в файлы APP.JAVA и SYSTEMSPECIFIC.CPP соответственно, то для их компиляции необходимо выполнить следующие команды (предполагается, что исходные файлы находятся в каталоге C:\TEST\NATIVE):
C:\TEST\NATIVE> JAVAC APP.JAVAC:\TEST\NATIVE> JAVAH -JNI SYSTEMSPECIFIC
C:\TEST\NATIVE> CL -W3 SYSTEMSPECIFIC.CPP -FESYSSPEC.DLL -TP -LD -MD -LINK JAVAI.LIB
Для запуска программы необходимо выполнить: C:\TEST\NATIVE> JAVA APP
на диске С:\ свободно 324567 KB
C:\TEST\NATIVE>
Для трансляции С/С++-файлов можно использовать любой компилятор, допускающий создание 32-битных DLL.