Bonjour,
Je suis en train de me faire un petit exemple d'utilisation de JNI, une addition en C++ appelé en Java.
J'utilise parfois des doubles, parfois des objets, parfois des pointeurs ... des exemples quoi.

Par contre je suis un peu "inquiet" ... En C++ on récupère un jobject, puis à partir de ce dernier on reconstruit l'objet C++ qui nous intéresse en passant par des objets primaires (doubles) ... mais ca me semble assez limité, si on a 10 cascades d'objet par exemple !

Est-ce que j'utilise comme il faut JNI ?

Voici mon exemple (avec du JNA pour comparaison):

Java : jni.JNIAddition
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
 
package jni;
 
import com.sun.jna.Pointer;
 
import jna.struc.ThreeDoubles;
import jna.struc.TwoDoubles;
 
public final class JNIAddition {
 
	static {
		System.loadLibrary("JNIAddition");
	}
 
	public static final native double addition(double a, double b);
 
	public static final native double additionP(Pointer a, Pointer b);
 
	public static final native double addition0(TwoDoubles a);
 
	public static final native double addition3(ThreeDoubles a);
 
}

Java : jna.MyLibs
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
 
package jna;
 
import java.util.Date;
 
import jna.struc.ThreeDoubles;
import jna.struc.TwoDoubles;
import jni.JNIAddition;
 
import com.sun.jna.Library;
import com.sun.jna.Memory;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.ptr.PointerByReference;
 
public class MyLibs {
 
	//use JNI implementation, if false use JNA
	static final boolean useJNIImplementation = true;
	static final int nbaddition = 10000000;
 
	   public interface AfficheLib extends Library {
		   public void affiche(String text);
	   }
 
	   public interface MathFuncsLib extends Library {
	        public double Add(double a, double b);
	   }
 
	   public interface AdditionLib extends Library {
	        public double addition(double a, double b);
	        public double additionP(Pointer a, Pointer b);
	        public double additionO(TwoDoubles a);
	        public double addition3(ThreeDoubles a);
	   }
 
 
	   public static void main(String[] args) {
 
		   if(useJNIImplementation) {
				   double value = JNIAddition.addition(1, 2);
				   System.out.println("1+2="+value);
 
				   TwoDoubles twoDouble = new TwoDoubles(2,3);
				   double value2 = JNIAddition.addition0(twoDouble);
				   System.out.println("2+3="+value2);
 
				   ThreeDoubles threeDouble = new ThreeDoubles(4, twoDouble);
				   double value3 = JNIAddition.addition3(threeDouble);
				   System.out.println("2+3+4="+value3);
		   } else {
 
			   AfficheLib affichelib = (AfficheLib) Native.loadLibrary("affiche", AfficheLib.class);
			   MathFuncsLib mathlib = (MathFuncsLib) Native.loadLibrary("MathFuncsLib", MathFuncsLib.class);
			   AdditionLib additionlib = (AdditionLib) Native.loadLibrary("addition", AdditionLib.class);
 
			   //Addition simple
			   double value = additionlib.addition(1, 2);
			   affichelib.affiche("1+2="+value);
 
			   PointerByReference val1 = new PointerByReference();
			   val1.setPointer(new Memory(Double.SIZE));
			   val1.getPointer().setDouble(0, 1);
 
			   //Addition simple pointer
			   double value2 = additionlib.additionP(val1.getPointer(), val1.getPointer());
			   affichelib.affiche("1+1="+value2);
 
			   //Addition objet
			   TwoDoubles twoDouble = new TwoDoubles(2,3);
			   double value3 = additionlib.additionO(twoDouble);
			   affichelib.affiche("2+3="+value3);
 
			   //Addition objet d'objet
			   ThreeDoubles threeDouble = new ThreeDoubles(4, twoDouble);
			   double value4 = additionlib.addition3(threeDouble);
			   affichelib.affiche("2+3+4="+value4);
 
		   }
 
/*
		   AdditionLib additionlib = (AdditionLib) Native.loadLibrary("addition", AdditionLib.class);
		   Date dateDepartJNA = new Date();
 
		   for(int i=0;i<nbaddition;i++) {
			   additionlib.addition(1, 2);
		   }
 
		   Date dateFinJNA = new Date();
		   long diffJNA = dateFinJNA.getTime()-dateDepartJNA.getTime();
 
		   System.out.println("Temps JNA = " + (diffJNA) + " ms.");
 
		   Date dateDepartJNI = new Date();
 
		   for(int i=0;i<nbaddition;i++) {
			   JNIAddition.addition0(new TwoDoubles(1,2));
		   }
 
		   Date dateFinJNI = new Date();
		   long diffJNI = dateFinJNI.getTime()-dateDepartJNI.getTime();
 
		   System.out.println("Temps JNI = " + (diffJNI) + " ms.");
		   */
	   }
}
Java : jna.struc.TwoDoubles
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
 
package jna.struc;
 
import com.sun.jna.Structure;
 
public class TwoDoubles extends Structure {
 
	public static int SIZE = Double.SIZE*2;
 
	public double val1;
	public double val2;
 
	public TwoDoubles() {
 
	}
 
	public TwoDoubles(double val1, double val2) {
		this.val1=val1;
		this.val2=val2;
	}
 
 
}
Java : jna.struc.ThreeDoubles
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
 
package jna.struc;
 
import com.sun.jna.Structure;
 
public class ThreeDoubles extends Structure {
 
	public double val1;
	public TwoDoubles val2;
 
 
	public ThreeDoubles() {
 
	}
 
	public ThreeDoubles(double val1, TwoDoubles val2) {
		this.val1=val1;
		this.val2=val2;
	}
 
 
}
C++ : jni_JNIAddition.h
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
 
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class jni_JNIAddition */
 
#ifndef _Included_jni_JNIAddition
#define _Included_jni_JNIAddition
#ifdef __cplusplus
extern "C" {
#endif
 
 
class TwoDoubles
{
public:
      double  value1;
      double  value2;
 
      TwoDoubles();
      TwoDoubles(double  value1, double  value2);
//      ~TwoDoubles();
};
 
 
class ThreeDoubles
{
public:
      double      value1;
      TwoDoubles  value2;
 
      ThreeDoubles();
      ThreeDoubles(double  value1, TwoDoubles  value2);
//      ~ThreeDoubles();
};
 
class Addition
{
public:
	  Addition();
      double additionne(double val1, double val2);
      double additionne(TwoDoubles* val1);
      double additionne(ThreeDoubles val1);
};
 
 
/*
 * Class:     jni_JNIAddition
 * Method:    addition
 * Signature: (DD)D
 */
JNIEXPORT jdouble JNICALL Java_jni_JNIAddition_addition
  (JNIEnv *, jclass, jdouble, jdouble);
 
/*
 * Class:     jni_JNIAddition
 * Method:    additionP
 * Signature: (Lcom/sun/jna/Pointer;Lcom/sun/jna/Pointer;)D
 */
JNIEXPORT jdouble JNICALL Java_jni_JNIAddition_additionP
  (JNIEnv *, jclass, jobject, jobject);
 
/*
 * Class:     jni_JNIAddition
 * Method:    addition0
 * Signature: (Ljna/struc/TwoDoubles;)D
 */
JNIEXPORT jdouble JNICALL Java_jni_JNIAddition_addition0
  (JNIEnv *, jclass, jobject);
 
/*
 * Class:     jni_JNIAddition
 * Method:    addition3
 * Signature: (Ljna/struc/ThreeDoubles;)D
 */
JNIEXPORT jdouble JNICALL Java_jni_JNIAddition_addition3
  (JNIEnv *, jclass, jobject);
 
#ifdef __cplusplus
}
#endif
#endif

C++ : jni_JNIAddition.cpp
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
 
//#include "addition.h"
#include "jni_JNIAddition.h"
 
TwoDoubles::TwoDoubles() {}
TwoDoubles::TwoDoubles(double val1, double val2) : value1(val1), value2(val2) {}
 
 
ThreeDoubles::ThreeDoubles() {}
ThreeDoubles::ThreeDoubles(double val1, TwoDoubles val2) : value1(val1), value2(val2) {}
 
 
Addition::Addition() {}
double Addition::additionne(double val1, double val2)
{
	return val1+val2;
}
double Addition::additionne(TwoDoubles* twoDoubles)
{
	return twoDoubles->value1+twoDoubles->value2;
}
double Addition::additionne(ThreeDoubles threeDoubles)
{
	TwoDoubles twoDoubles = threeDoubles.value2;
	return threeDoubles.value1+additionne(&twoDoubles);
}
 
 
 
 
 
JNIEXPORT jdouble JNICALL Java_jni_JNIAddition_addition
  (JNIEnv *env, jclass theClass, jdouble a, jdouble b) {
	Addition* add = new Addition;
	return add->additionne(a,b);
  }
 
 
JNIEXPORT jdouble JNICALL Java_jni_JNIAddition_additionP
  (JNIEnv *env, jclass theClass, jobject a, jobject b) {
  	return -1;
  }
 
 
JNIEXPORT jdouble JNICALL Java_jni_JNIAddition_addition0
  (JNIEnv *env, jclass theClass, jobject obj) {
 
	jclass clazz;
	jfieldID fid1;
	jfieldID fid2;
	double value1;
	double value2;
 
	clazz = env->GetObjectClass(obj);
 
	fid1 = env->GetFieldID(clazz, "val1", "D"); //le string est le nom de la variable java ...
	if(fid1==0) {
		return -1;
	}
	value1 = env->GetDoubleField(obj,fid1);
 
	fid2 = env->GetFieldID(clazz, "val2", "D"); //le string est le nom de la variable java ...
	if(fid2==0) {
		return -1;
	}
	value2 = env->GetDoubleField(obj,fid2);
 
	Addition* add = new Addition;
	return add->additionne(new TwoDoubles(value1,value2));
  }
 
 
JNIEXPORT jdouble JNICALL Java_jni_JNIAddition_addition3
  (JNIEnv *env, jclass theClass, jobject obj) {
 
	jclass clazz;
	jfieldID fid1;
	jfieldID fid2;
	double value1;
	jobject value2;
	double value31;
	double value32;
 
	clazz = env->GetObjectClass(obj);
 
	fid1 = env->GetFieldID(clazz, "val1", "D"); //le string est le nom de la variable java ...
	if(fid1==0) {
		return -1;
	}
	value1 = env->GetDoubleField(obj,fid1);
 
	fid2 = env->GetFieldID(clazz, "val2", "Ljna/struc/TwoDoubles;"); //le string est le nom de la variable java ...
	if(fid2==0) {
		return -1;
	}
	value2 = env->GetObjectField(obj,fid2);
 
	jclass clazz2 = env->GetObjectClass(value2);
	jfieldID fid21 = env->GetFieldID(clazz2, "val1", "D");
	jfieldID fid22 = env->GetFieldID(clazz2, "val2", "D");
 
	value31 = env->GetDoubleField(value2,fid21);
	value32 = env->GetDoubleField(value2,fid22);
 
	TwoDoubles twoDoubles(value31, value32);
	ThreeDoubles threeDoubles(value1, twoDoubles);
 
	Addition* add = new Addition;
  	return add->additionne(threeDoubles);
  }
Merci à vous.