28 Kasım 2018 Çarşamba

JNI - Java'dan CPP'yi çağırmak

Giriş
Cpp kodu şöyledir.
JNIEXPORT MethodReturnType JNICALL Java_fullclassname_methodname
Diğer
Java'dan çağırmak için
1. Java kodu içinde
public static native MethodReturnType MethodName(MethodParameters);
şeklinde metod tanımlamaları yapılır.
2. Java kodu içinde System.loadLibrary() çağrısı ile .dll veya .so yüklenir.
3. fullclassname ile sınıf yaratılır ve metodu çağrılır

Örnek - Java'dan CPP Üretmek
Elimizde şöyle bir Java kodu olsun
package sample;

public class CalculateMath {
  static {
    System.loadLibrary("mathlib");
  }
  public native int calcSquare(int n);
}
Header dosyası üretmek için şöyle yaparız
javac -h . sample/CalculateMath.java
Üretilen sample_CalculateMath.h dosyası şöyledir
include <jni.h>
/* Header for class sample_CalculateMath */
                        
#ifndef _Included_sample_CalculateMath
#define _Included_sample_CalculateMath
#ifdef __cplusplus
extern "C" {
#endif

  /*
   * Class:     sample_CalculateMath
   * Method:    calcSquare
   * Signature: (I)I
   */
  JNIEXPORT jint JNICALL Java_sample_CalculateMath_calcSquare (JNIEnv *, jobject, jint);
        
#ifdef __cplusplus
}
#endif
#endif
CalculateMath.c dosyasının içini dolduralım
#include "sample_CalculateMath.h"
#include <string.h>

JNIEXPORT jint JNICALL Java_sample_CalculateMath_calcSquare
  (JNIEnv *env, jobject obj, jint num) {
   return num * num;
}

void main(){}
libmathlib.so ismide bir shared object derleyim
gcc -fPIC -I"$JAVA_HOME/include" -I"$JAVA_HOME/include/linux" -shared -o libmathlib.so
CalculateMath.c
Örnek
Java kodu şöyle olsun.
public class JNItest2 {

public native void helloworld(String[] args);

  static{
    System.loadLibrary("Dense");        
  }
  public static void main(String[] args)
  {        
    new JNItest2().helloworld(args);
  }
}
C metod ismi Java ile başlar, Java sınıf ismi eklenir, metod ismi eklenir. 
İlk parametre JNIEnv, 
İkinci parametre metodu ihtiva eden nesnedir. Eğer metod static ise bu parametreye gerek yok. 
Diğer parametreler metoda geçilen değerler. 

Şöyle yaparız.
JNIEXPORT void JNICALL
Java_JNItest2_helloworld(JNIEnv *env,jobject object, jobjectArray args)
{
...
}   
Örnek
Şöyle yaparız.
#include <jni.h>
#include <string>

extern "C"
JNIEXPORT jstring JNICALL
Java_com_android_app_aesKeyFromJNI(JNIEnv *env, jobject /* this */) {
    std::string secret = "somesecretkey";
    return env->NewStringUTF(secret.c_str());
}
Örnek
Şöyle yaparız.
JNIEXPORT jlong JNICALL Java_com_mypackage_ClipboardHelper_initialize
    (JNIEnv *env, jclass obj, jstring arg) {
Örnek
Şöyle yaparız.
header dosyasında şu include yapılır
#include <jni.h>
cpp şuna benzer.
JNIEXPORT jstring JNICALL Java_six_pack_Neatifier_neatify(JNIEnv* env, 
                                                          jclass clazz, 
                                                          jlong val, 
                                                          jchar pad, 
                                                          jint span)
{
   ... 
   jstring ret = env->NewStringUTF(out);
   return ret;
}
Java'dan DLL'i yükleriz.
System.load(System.getProperty("user.dir") + File.separator +
                        "src" + File.separator + "mylib.jnilib");
Java içinde Cpp ile aynı imzayı taşıyan bir metod tanımlarız.
public static native String neatify(final long val,
                                    final char pad,
                                    final int span);
Metodu çağırırız.
neatify(l, '_', 3);
Örnek
Elimizde şöyle bir java kodu olsun. HashMap parametre olarak metoda geçiliyor.
import java.util.*;  
class javasam{  
  private native void print(HashMap<String,String> hm);
  public static void main(String args[]){  
    HashMap<String,String> hm=new HashMap<String,String>();   
    hm.put("100","Amit");  
    hm.put("101","Vijay");  
    hm.put("102","Rahul");  
    new javasam().print(hm);
  }  
  static {
    System.loadLibrary("javasam");
  }  
}
cpp kodu şöyle olsun. Parametre olarak geçilen nesneye erişiliyor.
#include "stdafx.h"
#include <stdio.h>
#include <jni.h>
#include "javasam.h"
#include <string.h>
#include <map>
#include <iostream>
JNIEXPORT void JNICALL Java_javasam_print (JNIEnv *s, jobject k, jobject l)
{
  jclass mapclass = s->GetObjectClass(l);
  ...
}

Hiç yorum yok:

Yorum Gönder