русс | укр

Мови програмуванняВідео уроки php mysqlПаскальСіАсемблерJavaMatlabPhpHtmlJavaScriptCSSC#DelphiТурбо Пролог

Компьютерные сетиСистемное программное обеспечениеИнформационные технологииПрограммирование


Linux Unix Алгоритмічні мови Архітектура мікроконтролерів Введення в розробку розподілених інформаційних систем Дискретна математика Інформаційне обслуговування користувачів Інформація та моделювання в управлінні виробництвом Комп'ютерна графіка Лекції


Підключення зовнішніх бібліотек DLL. «Рідні» (native) методи


Дата додавання: 2014-05-29; переглядів: 1142.


Для прикладного програмування засобів Java у переважній більшості випадків вистачає. Однак іноді виникає необхідність підключити до програми ряд системних викликів. Або забезпечити доступ до бібліотек, написаним на інших мовах програмування. Для таких цілей в Java використовуються методи, оголошені з модифікатором native - "рідний". Це слово означає, що при виконанні методу виробляється виклик "рідного" для конкретної платформи двійкового коду, а не платформо-незалежного байта-коду як у всіх інших випадках. Заголовок "рідного" методу описується в класі Java, а його реалізація здійснюється на якому-небудь із мов програмування, що дозволяють створювати бібліотеки, що підключаються динамічно (DLL - Dynamic Link Library під Windows, Shared Objects під UNIX-Образними операційними системами).

Правило для оголошення й реалізації таких методів зветься JNI - Java Native Interface.

Оголошення "рідного" методу в Java має вигляд

 

Модифікатори native Повертаємий_типім.’я_методу(список параметрів);

 

Тіло «рідного» методу не задається - воно є зовнішнім і завантажується на згадку комп'ютера за допомогою завантаження тої бібліотеки, з якої цей метод повинен викликатися:

 

System.loadLibrary(«Ім’я_бібліотеки»);

 

При цьому ім'я бібліотеки задається без шляху й без розширення. Наприклад, якщо під Windows бібліотека має ім'я myLib.dll, або під UNIX або Linux має ім'я myLib.so, треба вказувати System.loadLibrary(«myLib») ;

У випадку, якщо файлу не знайдено, збуджується непроверяемая виняткова ситуація UnsatisfiedLinkError.

Якщо потрібно вказати ім'я бібліотеки зі шляхом, застосовується виклик

 

System.load («Ім’я_бібліотеки_з_шляхом»);

 

Який у всім іншому абсолютно аналогічний виклику loadLibrary.

Після того, як бібліотека завантажена, з погляду використання в програмі виклик "рідного" методу нічим не відрізняється від виклику будь-якого іншого методу.

Для створення бібліотеки з методами, призначеними для роботи в якості "рідних", звичайно використовується мова С++. В JDK існує утиліта javah.exe, призначена для створення заголовків C++ зі скомпільованих класів Java. Покажемо, як їй користуватися, на прикладі класу ClassWithNativeMethod. Задамо його в пакеті нашого додатка:

 

package java_example_pkg;

public class ClassWithNativeMethod {

/** Creates a new instance of ClassWithNativeMethod */

public ClassWithNativeMethod() {

}

public native void myNativeMethod();

}

 

Для того, щоб скористатися утилітою javah, скомпілюємо проект і перейдемо в папку build\classes. У ній будуть розташовуватися папка з пакетом нашого додатка java_example_pkg і папка META-INF. У режимі командного рядка виконаємо команду

 

javah.exe java_example_pkg.ClassWithNativeMethod

 

Задавати ім'я класу необхідно з повною кваліфікацією, тобто із вказівкою перед ним ім'я пакета. У результаті в папці з'явиться файл java_example_pkg_ClassWithNativeMethod.h з наступним умістом:

 

/* DO NOT EDIT THIS FILE - it is machine generated */

#include <jni.h>

/* Header for class java_example_pkg_ClassWithNativeMethod */

#ifndef _Included_java_example_pkg_ClassWithNativeMethod

#define _Included_java_example_pkg_ClassWithNativeMethod

#ifdef __cplusplus

extern "C" {

#endif

/*

* Class: java_example_pkg_ClassWithNativeMethod

* Method: myNativeMethod

* Signature: ()V

*/

JNIEXPORT void JNICALL

Java_java_1example_1pkg_ClassWithNativeMethod_myNativeMethod

(JNIEnv *, jobject);

#ifdef __cplusplus

}

#endif

#endif

 

Функція Java_java_1example_1pkg_ClassWithNativeMethod_myNativeMethod(JNIEnv *, jobject), написана на C++, повинна забезпечувати реалізацію методу myNativeMethod() у класі Java. Ім'я функції C++ складається з: префікса Java, роздільника "_", модифікованого ім'я пакета (знаки підкреслення "_" заміняються на "_1"), роздільника "_", ім'я класу, роздільника "_", ім'я "рідного" методу. Перший параметр JNIEnv * у функції C++ забезпечує доступ "рідного" коду до параметрів і об'єктів, що передається з функції C++ в Java. Зокрема, для доступу до стеку. Другий параметр, jobject, - посилання на екземпляр класу, у якому заданий "рідний" метод, для методів об'єкта, і jclass - посилання на сам клас - для методів класу. У мові C++ немає посилань, але в Java всі змінні об'єктного типу є посиланнями. Відповідно, другий параметр ототожнюється із цієї змінної.

У реалізації методу потрібно оголосити змінні. Наприклад, якщо ми будемо обчислювати квадрат переданого в метод значення й повертати як результат значення параметра, зведене у квадрат (приклад чисто навчальний), код реалізації функції на C++ буде виглядати так:

 

#include "java_example_pkg_ClassWithNativeMethod.h"

JNIEXPORT jint JNICALL

Java_java_1example_1pkg_ClassWithNativeMethod_myNativeMethod

(JNIEnv *env, jobject obj, jint i ){

return i*i

};

 

Відзначимо, що при роботі з рядками й масивами для одержання й передачі параметрів потрібно використовувати змінну env. Наприклад, одержання довжини цілого масиву, переданого в змінну jintArray intArr, буде виглядати так:

 

jsize length=(*env)->GetArrayLength(env, intArr);

 

Виділення пам'яті під переданий масив:

 

jint *intArrRef=(*env)->GetIntArrayElements(env, intArr,0);

 

Далі з масивом intArr можна працювати як зі звичайним масивом C++. Вивільнення пам'яті з-під масиву:

 

(*env)->ReleaseIntArrayElements(env, intArr, intArrRef ,0);

Є аналогічні функції для доступу до елементів масивів всіх примітивних типів: GetBooleanArrayElements, GetByteArrayElements,..., GetDoubleArrayElements. Ці функції копіюють уміст масивів Java у нову область пам'яті, з якої і йде робота в C++. Для масивів об'єктів є не тільки функція GetObjectArrayElement, але й SetObjectArrayElement - для одержання й зміни окремих елементів таких масивів.

Рядок Java jstring s перетвориться в масив символів C++ так:

 

const char *sRef=(*env)->GetStringUTFChars(env,s,0);


 


<== попередня лекція | наступна лекція ==>
Тема 13 Підключення зовнішніх бібліотек | Тема 14 Можливості Java для обміну і передачі інформації. Робота з файловою системою. Пакет java.io


Онлайн система числення Калькулятор онлайн звичайний Науковий калькулятор онлайн