खोज…


पैरामीटर

पैरामीटर विवरण
JNIEnv जेएनआई पर्यावरण की ओर इशारा करता है
jobject वह वस्तु जिसने गैर- static native पद्धति को लागू किया
jclass वह वर्ग जिसने static native पद्धति को लागू किया

टिप्पणियों

जेएनआई की स्थापना के लिए जावा और देशी कंपाइलर दोनों की आवश्यकता होती है। आईडीई और ओएस के आधार पर, कुछ सेटिंग की आवश्यकता होती है। ग्रहण के लिए एक गाइड यहाँ पाया जा सकता है । एक पूर्ण ट्यूटोरियल यहां पाया जा सकता है

ये विंडोज़ पर Java-C ++ लिंकेज स्थापित करने के लिए चरण हैं:

  • जावा स्रोत फ़ाइलों ( .java ) को javac का उपयोग करके कक्षाओं ( .class ) में संकलित करें।
  • जावा का उपयोग करके native तरीकों से जावा वर्गों से हेडर ( .h ) फाइलें javah । ये फाइलें मूल कोड को "निर्देश" देती हैं जो इसे लागू करने के लिए जिम्मेदार हैं।
  • native तरीकों को लागू करने वाले C ++ स्रोत फ़ाइलों ( .cpp ) में हेडर फाइलें ( #include ) शामिल करें।
  • C ++ स्रोत फ़ाइलों को संकलित करें और एक लाइब्रेरी ( .dll ) बनाएं। इस लाइब्रेरी में देशी कोड कार्यान्वयन है।
  • लाइब्रेरी पथ ( -Djava.library.path ) निर्दिष्ट करें और इसे जावा स्रोत फ़ाइल ( System.loadLibrary(...) ) में लोड करें।

कॉलबैक (देशी कोड से जावा विधियों को कॉल करना) के लिए एक विधि विवरणक निर्दिष्ट करना होगा। यदि वर्णनकर्ता गलत है, तो रनटाइम त्रुटि होती है। इस वजह से, यह हमारे लिए किए गए विवरणों के लिए सहायक है, यह javap -s साथ किया जा सकता है।

जावा से C ++ विधियों को कॉल करना

जावा में स्थिर और सदस्य विधियों को मूल के रूप में चिह्नित किया जा सकता है ताकि यह इंगित किया जा सके कि उनका कार्यान्वयन एक साझा पुस्तकालय फ़ाइल में पाया जाना है। एक मूल विधि के निष्पादन पर, जेवीएम लोड किए गए पुस्तकालयों में एक समान कार्य की तलाश करता है (देखें देशी पुस्तकालयों को लोड करें ), एक साधारण नाम प्रबंधन योजना का उपयोग करते हुए, तर्क रूपांतरण और स्टैक सेटअप का प्रदर्शन करता है, फिर मूल कोड पर नियंत्रण सौंपता है।

जावा कोड

/*** com/example/jni/JNIJava.java **/

package com.example.jni;

public class JNIJava {
    static {
        System.loadLibrary("libJNI_CPP");
    }

    // Obviously, native methods may not have a body defined in Java
    public native void printString(String name);
    public static native double average(int[] nums);

    public static void main(final String[] args) {
        JNIJava jniJava = new JNIJava();
        jniJava.printString("Invoked C++ 'printString' from Java");

        double d = average(new int[]{1, 2, 3, 4, 7});
        System.out.println("Got result from C++ 'average': " + d);
    }
}

C ++ कोड

लक्ष्य वर्गों पर javah टूल का उपयोग करके देशी फ़ंक्शन घोषणाओं वाली हैडर फाइलें उत्पन्न की जानी चाहिए। बिल्ड डायरेक्टरी में निम्न कमांड चला रहे हैं:

javah -o com_example_jni_JNIJava.hpp com.example.jni.JNIJava

... निम्नलिखित हेडर फ़ाइल का निर्माण करता है ( संक्षिप्तता के लिए छपी टिप्पणियाँ ):

// com_example_jni_JNIJava.hpp

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h> // The JNI API declarations

#ifndef _Included_com_example_jni_JNIJava
#define _Included_com_example_jni_JNIJava
#ifdef __cplusplus
extern "C" { // This is absolutely required if using a C++ compiler
#endif

JNIEXPORT void JNICALL Java_com_example_jni_JNIJava_printString
  (JNIEnv *, jobject, jstring);

JNIEXPORT jdouble JNICALL Java_com_example_jni_JNIJava_average
  (JNIEnv *, jclass, jintArray);

#ifdef __cplusplus
}
#endif
#endif

यहाँ एक उदाहरण कार्यान्वयन है:

// com_example_jni_JNIJava.cpp

#include <iostream>
#include "com_example_jni_JNIJava.hpp"

using namespace std;

JNIEXPORT void JNICALL Java_com_example_jni_JNIJava_printString(JNIEnv *env, jobject jthis, jstring string) {
    const char *stringInC = env->GetStringUTFChars(string, NULL);
    if (NULL == stringInC)
        return;
    cout << stringInC << endl;
    env->ReleaseStringUTFChars(string, stringInC);
}

JNIEXPORT jdouble JNICALL Java_com_example_jni_JNIJava_average(JNIEnv *env, jclass jthis, jintArray intArray) {
    jint *intArrayInC = env->GetIntArrayElements(intArray, NULL);
    if (NULL == intArrayInC)
        return -1;
    jsize length = env->GetArrayLength(intArray);
    int sum = 0;
    for (int i = 0; i < length; i++) {
        sum += intArrayInC[i];
    }
    env->ReleaseIntArrayElements(intArray, intArrayInC, 0);
    return (double) sum / length;
}

उत्पादन

ऊपर दिए गए उदाहरण वर्ग को चलाने से निम्नलिखित आउटपुट मिलते हैं:

जावा से C ++ 'PrintString' का आह्वान किया
सी ++ 'औसत' से परिणाम मिला: 3.4

C ++ (कॉलबैक) से जावा विधियों को कॉल करना

मूल विधि से जावा विधि को कॉल करना दो चरणों वाली प्रक्रिया है:

  1. GetMethodID JNI फ़ंक्शन के साथ एक विधि सूचक प्राप्त करें, विधि नाम और विवरणक का उपयोग करके;
  2. कॉल की एक Call*Method यहाँ सूचीबद्ध कार्य करता है

जावा कोड

/*** com.example.jni.JNIJavaCallback.java ***/

package com.example.jni;

public class JNIJavaCallback {
    static {
        System.loadLibrary("libJNI_CPP");
    }
    
    public static void main(String[] args) {
        new JNIJavaCallback().callback();
    }

    public native void callback(); 

    public static void printNum(int i) {
        System.out.println("Got int from C++: " + i);
    }
    
    public void printFloat(float i) {
        System.out.println("Got float from C++: " + i);
    }
}

C ++ कोड

// com_example_jni_JNICppCallback.cpp

#include <iostream>
#include "com_example_jni_JNIJavaCallback.h"

using namespace std;

JNIEXPORT void JNICALL Java_com_example_jni_JNIJavaCallback_callback(JNIEnv *env, jobject jthis) {
    jclass thisClass = env->GetObjectClass(jthis);

    jmethodID printFloat = env->GetMethodID(thisClass, "printFloat", "(F)V");
    if (NULL == printFloat)
        return;
    env->CallVoidMethod(jthis, printFloat, 5.221);

    jmethodID staticPrintInt = env->GetStaticMethodID(thisClass, "printNum", "(I)V");
    if (NULL == staticPrintInt)
        return;
    env->CallVoidMethod(jthis, staticPrintInt, 17);
}

उत्पादन

C ++: 5.221 से फ्लोट हुआ
C ++: 17 से int प्राप्त किया

वर्णन करने वाला

संकलित .class फ़ाइल पर javap प्रोग्राम का उपयोग करके डिस्क्रिप्टर्स (या आंतरिक प्रकार के हस्ताक्षर ) प्राप्त किए जाते हैं। यहाँ javap -p -s com.example.jni.JNIJavaCallback का आउटपुट है:

Compiled from "JNIJavaCallback.java"
public class com.example.jni.JNIJavaCallback {
  static {};
    descriptor: ()V

  public com.example.jni.JNIJavaCallback();
    descriptor: ()V

  public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V

  public native void callback();
    descriptor: ()V

  public static void printNum(int);
    descriptor: (I)V  // <---- Needed

  public void printFloat(float);
    descriptor: (F)V  // <---- Needed
}

देशी पुस्तकालय लोड हो रहे हैं

जावा में साझा लाइब्रेरी फ़ाइलों को लोड करने के लिए सामान्य मुहावरे निम्नलिखित हैं:

public class ClassWithNativeMethods {
    static {
        System.loadLibrary("Example");
    }

    public native void someNativeMethod(String arg);
    ...

System.loadLibrary को कॉल लगभग हमेशा स्थिर होती है ताकि क्लास लोडिंग के दौरान हो सके, यह सुनिश्चित करें कि साझा लाइब्रेरी लोड होने से पहले कोई भी देशी विधि निष्पादित नहीं हो सके। हालांकि निम्नलिखित संभव है:

public class ClassWithNativeMethods {
    // Call this before using any native method
    public static void prepareNativeMethods() {
        System.loadLibrary("Example");
    }

    ...

यह आवश्यक होने तक साझा लाइब्रेरी लोडिंग को स्थगित करने की अनुमति देता है, लेकिन java.lang.UnsatisfiedLinkError s से बचने के लिए अतिरिक्त देखभाल की आवश्यकता होती है।

लक्ष्य फ़ाइल लुकअप

साझा लाइब्रेरी फ़ाइलों पथ द्वारा परिभाषित में खोज की जाती है java.library.path प्रणाली संपत्ति है, जो का उपयोग कर ओवरराइड किया जा सकता -Djava.library.path= रनटाइम पर JVM तर्क:

java -Djava.library.path=path/to/lib/:path/to/other/lib MainClassWithNativeMethods

सिस्टम पथ विभाजकों के लिए देखें: उदाहरण के लिए, विंडोज उपयोग करता है ; के बजाय :

ध्यान दें कि System.loadLibrary एक प्लेटफ़ॉर्म-आश्रित तरीके से लाइब्रेरी फ़ाइलनाम को हल करता है: ऊपर दिया गया कोड स्निपेट, Linux पर libExample.so नामक फ़ाइल और Windows पर Example.dll अपेक्षा करता है।

के लिए एक वैकल्पिक System.loadLibrary है System.load(String) है, जो एक साझा लाइब्रेरी फ़ाइल का पूर्ण पथ लेता है, circumventing java.library.path देखने:

public class ClassWithNativeMethods {
    static {
        System.load("/path/to/lib/libExample.so");
    }

    ...


Modified text is an extract of the original Stack Overflow Documentation
के तहत लाइसेंस प्राप्त है CC BY-SA 3.0
से संबद्ध नहीं है Stack Overflow