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
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
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.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
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; } }
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 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; } }
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
Merci à vous.
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); }
Partager