Introduction au dévellopement de Methodes Natives Partie II : Echange de données entre java et C++. Auteur: Frank Sauvage.

Documents pareils
Systeme d'exploitation

Cours Java Native Interface

Derrière toi Une machine virtuelle!

Généralités sur le Langage Java et éléments syntaxiques.

Programmation avancée et répartie en Java : interfaçage avec d autres langages

Pour signifier qu'une classe fille hérite d'une classe mère, on utilise le mot clé extends class fille extends mère

Programmer en JAVA. par Tama

INTRODUCTION A JAVA. Fichier en langage machine Exécutable

Structure d un programme et Compilation Notions de classe et d objet Syntaxe

Chapitre 10. Les interfaces Comparable et Comparator 1

Le langage C++ est un langage de programmation puissant, polyvalent, on serait presque tenté de dire universel, massivement utilisé dans l'industrie

as Architecture des Systèmes d Information

Cours 1: Java et les objets

Page 1 sur 5 TP3. Thèmes du TP : l la classe Object. l Vector<T> l tutorial Interfaces. l Stack<T>

Plan du cours. Historique du langage Nouveautés de Java 7

Introduction à Java. Matthieu Herrb CNRS-LAAS. Mars

TP1 : Initiation à Java et Eclipse

Java Licence Professionnelle CISII,

Introduction au langage C

1. Structure d un programme C. 2. Commentaire: /*..texte */ On utilise aussi le commentaire du C++ qui est valable pour C: 3.

INITIATION AU LANGAGE C SUR PIC DE MICROSHIP

TD3: tableaux avancées, première classe et chaînes

TP n 2 Concepts de la programmation Objets Master 1 mention IL, semestre 2 Le type Abstrait Pile

ACTIVITÉ DE PROGRAMMATION

Une introduction à Java

P r ob lé m a t iq u e d e la g é n é r icit é. Pr in cip e d e la g é n é r icit é e n Ja v a ( 1 /3 )

1.6- Génération de nombres aléatoires

Info0101 Intro. à l'algorithmique et à la programmation. Cours 3. Le langage Java

Premiers Pas en Programmation Objet : les Classes et les Objets

I. Introduction aux fonctions : les fonctions standards

Package Java.util Classe générique

Initiation à JAVA et à la programmation objet.

Cours intensif Java. 1er cours: de C à Java. Enrica DUCHI LIAFA, Paris 7. Septembre Enrica.Duchi@liafa.jussieu.fr

Héritage presque multiple en Java (1/2)

Java 7 Les fondamentaux du langage Java

Java Licence Professionnelle Cours 7 : Classes et méthodes abstraites

RMI le langage Java XII-1 JMF

RMI. Remote Method Invocation: permet d'invoquer des méthodes d'objets distants.

INITIATION AU LANGAGE JAVA

Programmation par les Objets en Java

Cahier des charges. driver WIFI pour chipset Ralink RT2571W. sur hardware ARM7

Chapitre 2. Classes et objets

Java Licence Professionnelle CISII, Cours 2 : Classes et Objets

OS Réseaux et Programmation Système - C5

Programmation Orientée Objet

Rappels Entrées -Sorties

Cours d Algorithmique-Programmation 2 e partie (IAP2): programmation 24 octobre 2007impérative 1 / 44 et. structures de données simples

Auto-évaluation Programmation en Java

Remote Method Invocation (RMI)

Programme Compte bancaire (code)

Java DataBaseConnectivity

Exceptions. 1 Entrées/sorties. Objectif. Manipuler les exceptions ;

Projet gestion d'objets dupliqués

Projet de programmation (IK3) : TP n 1 Correction

Tp 1 correction. Structures de données (IF2)

Applet pour visualiser les variables «automate» notifiées

Bases du langage. Historique Applications et applets Éléments de base du langage Classes et objets Les exceptions

LMI 2. Programmation Orientée Objet POO - Cours 9. Said Jabbour. jabbour@cril.univ-artois.fr

Projet de Veille Technologique

TP, première séquence d exercices.

Cours d Algorithmique et de Langage C v 3.0

Licence Bio Informatique Année Premiers pas. Exercice 1 Hello World parce qu il faut bien commencer par quelque chose...

C++ COURS N 2 : CLASSES, DONNÉES ET FONCTIONS MEMBRES Classes et objets en C++ Membres d'une classe Spécification d'une classe Codage du comportement

Programmation en Java IUT GEII (MC-II1) 1

Polycopié Cours Programmation Orientée Objet sous Java Programme : Filière SMI S5

Java Licence Professionnelle CISII,

Java - la plateforme

Cours 1 : Introduction. Langages objets. but du module. contrôle des connaissances. Pourquoi Java? présentation du module. Présentation de Java

Info0604 Programmation multi-threadée. Cours 5. Programmation multi-threadée en Java

TP1 : Initiation à Java et Eclipse

La technologie Java Card TM

UE Programmation Impérative Licence 2ème Année

Introduction aux Machines Virtuelles avec VMKit

Polymorphisme, la classe Object, les package et la visibilité en Java... 1

PROJET ALGORITHMIQUE ET PROGRAMMATION II

Corrigé des exercices sur les références

Compression de Données - Algorithme de Huffman Document de Conception

Exercices sur les interfaces

Machines virtuelles. Brique ASC. Samuel Tardieu Samuel Tardieu (ENST) Machines virtuelles 1 / 40

Brefs rappels sur la pile et le tas (Stack. / Heap) et les pointeurs

Langage Java. Classe de première SI

Introduction à JDBC. Accès aux bases de données en Java

RAPPORT DE STAGE. Licence Professionnelle Systèmes Informatiques et Logiciels spécialité Imagerie Numérique et Informatique

Introduction à la programmation concurrente

Encapsulation. L'encapsulation consiste à rendre les membres d'un objet plus ou moins visibles pour les autres objets.

RAPPELS SUR LES METHODES HERITEES DE LA CLASSE RACINE Object ET LEUR SPECIALISATION (i.e. REDEFINITION)

Utilisation d objets : String et ArrayList

Quelques éléments de compilation en C et makefiles

Cours d initiation à la programmation en C++ Johann Cuenin

Travaux pratiques. Compression en codage de Huffman Organisation d un projet de programmation

La carte à puce. Jean-Philippe Babau

TD Objets distribués n 3 : Windows XP et Visual Studio.NET. Introduction à.net Remoting

TD/TP PAC - Programmation n 3

Claude Delannoy. 3 e édition C++

Centre CPGE TSI - Safi 2010/2011. Algorithmique et programmation :

IFT287 Exploitation de base de données relationnelles et orientées objet. Laboratoire Mon premier programme Java en Eclipse

DE L ALGORITHME AU PROGRAMME INTRO AU LANGAGE C 51

Seance 2: En respectant la méthode de programmation par contrat, implémentez les autres fonctions de jeu.

EPREUVE OPTIONNELLE d INFORMATIQUE CORRIGE

Java c est quoi? Java. Java. Java : Principe de fonctionnement 31/01/ Vue générale 2 - Mon premier programme 3 - Types de Programme Java

Transcription:

Introduction au dévellopement de Methodes Natives Partie II : Echange de données entre java et C++. Auteur: Frank Sauvage. 1 \ Correspondance des données entre Java et C++ Dans le chapitre precedent, nous avons vu comment créer des fonctions natives simples en C++. Cependant dans le cadre d'une utilisation réelle, il est neccessaire de pouvoir echanger des données entre les 2 langages utilisés. Pour cela, la JNI fournit des types prédéfinis pouvant etre directement utilisés dans le langage C++. Le tableau suivant donne la correspondance de types alors utilisables. Type java Type natif Equivalent C++ boolean jboolean 8, unsigned byte jbyte 8 char jchar 16, unsigned short jshort 16 int jint 32 long jlong 64 float jfloat 32 double jdouble 64 void void n/a Les types ainsi presentés sont en fait des typedef definis dans le fichier d'include jni.h, ce qui à pour effet de pouvoir etre utilisés directement sans conversions de format. Il est alors juste neccessaire de garder à l'esprit que certains types sont equivalent à d'autres en C++, mais que la correspondance n'est pas forcement la plus évidente comme avec les Char codés sur 16bits en java. Voici un extrait du jni.h : typedef unsigned char jboolean; typedef unsigned short jchar; typedef short jshort; typedef float jfloat; typedef double jdouble; Note: le type jint est lui defini dans un fichier séparé dépendant du systéme d'exploitation. En effet, la taille des registres n'étant pas toujours la même, il est neccessaire de s'assurer de la compatibilité pour chaque plateforme cible où se trouve une machine virtuelle.

2 \ Premier exemple : une fonction pour additionner deux nombres. Notre premier exemple va nous permettre de voir comment echanger des données entre java et C++. pour cela, nous allons tacher d'implementer une methode native qui acceptera en parametre deux int et qui rendra une autre int contenant la somme des deux. Etape 1 : ecriture du code java : package testjni; public class FonctionAddition // chargement de la librairie associée static System.loadLibrary("testJNI_FonctionAddition"); //declaration de la fonction native. ne rends pas de resultat. public static native int fonctionaddition(int nb1, int nb2); public static void main(string[] args) int nb1 = 2; int nb2 = 4; System.out.println("l'addition de "+nb1+" et de "+nb2); System.out.println(" a pour resultat:"+fonctionaddition(nb1,nb2)); Etape 2 : generation du header C++ : comme dans le premier chapitre, on genere le resultat suivant a partir de la classe compilée. /* DO NOT EDIT THIS FILE - it is machine generated */ #include <jni.h> /* Header for class testjni_fonctionaddition */ #ifndef _Included_testJNI_FonctionAddition #define _Included_testJNI_FonctionAddition extern "C" /* * Class: testjni_fonctionaddition * Method: fonctionaddition * Signature: (II)I */ JNIEXPORT jint JNICALL Java_testJNI_FonctionAddition_fonctionAddition (JNIEnv *, jclass, jint, jint); comme on peut le voir ici, on obtient alors le prototype de la fonction suivante : JNIEXPORT jint JNICALL Java_testJNI_FonctionAddition_fonctionAddition (JNIEnv *, jclass, jint, jint); dans ce cas, précis on constate la présence de deux jint supplementaire vis à vis des parametres spéciaux. Ce sont donc bien les int que nous avons tenté de passer à la methode native.

Etape 3 : écriture du code C++ : pour écrire le code des fonctions en C++, il suffit de recuperer les prototypes de fonctions generés par javah et ensuite de les modifier afin de nommer les variables dont on devra se servir. Note : il n'est pas utile de renommer ces memes variables dans le prototype du fichier d'entete, cela est meme deconseillé afin de garder intacte l'integrité dudit fichier. #include "testjni_fonctionaddition.h" // on recupere le prototype depuis le fichier d'entete // et on nomme les parametres dont on aura besoin JNIEXPORT jint JNICALL Java_testJNI_FonctionAddition_fonctionAddition (JNIEnv *, jclass, jint nb1, jint nb2) // on recupere les valeurs de nb1 et de nb2 dans des variables locales. // cela est inutile, mais on le fait ici pour montrer l'equivalance des types. signed int a = nb1; signed int b = nb2; signed int res = a + b; return res; les types natifs sont utilisables directement, mais l'exemple ci dessus montre qu'il est possible sans aucune difficulté de les affecter à des variables declarées directement en C++. Etape 4 : compilation et execution : maintenant que nous avons ecris notre programme, nous pouvons donc le compiler et l'executer. Rappel sur la compilation : la commande suivante lance la compilation de notre librairie : cl /LD testjni_fonctionaddition.cpp A l'execution, l'exemple sur l'addition affiche le resultat suivant : l'addition de 2 et de 4 a pour resultat:6 Conclusion : l'exemple simple que nous venons de voir demontre la possibilité de passer des données de type intrinséques à Java grâce aux types natifs fournis par l'interface JNI.

3 \ utilisation des strings avec les méthodes natives. En java, une chaine de caractere est nativement un objet de base du langage surveillé par le ramasse miette. Il est donc neccessaire de passer par des fonctions de conversions afin de pouvoir les utiliser dans les methodes natives. l'exemple suivant donne une idée de l'utilisation des String dans les methodes natives. Il defini deux methodes, l'une pour recuperer une string, l'autre pour la passer en parametre. Etape 1 : declaration des methodes en java : De la meme maniere que pour toute methode native, on passe une string comme tout autre type de donnée. La difference au niveau implementation se situera au niveau du code C++. package testjni; public class FonctionsString // chargement de la librairie associée static System.loadLibrary("testJNI_FonctionsString"); // exemple de fonction utilisant une string en paramétre. public static native void ecrisstring(string chaine); // exemple de fonction renvoyant une String. public static native String recuperestring(); public static void main(string[] args) // on recupere la string a partir de la methode getstring(); String chaine = recuperestring(); // on imprime la string recuperée grace a la methode printstring() ecrisstring(chaine);

Etape 2 : Generation du fichier d'entete C++ : La generation de l'entete est maintenant une action familiere. Le fichier suivant est donc obtenu : /* DO NOT EDIT THIS FILE - it is machine generated */ #include <jni.h> /* Header for class testjni_fonctionsstring */ #ifndef _Included_testJNI_FonctionsString #define _Included_testJNI_FonctionsString extern "C" /* * Class: testjni_fonctionsstring * Method: ecrisstring * Signature: (Ljava/lang/String;)V */ JNIEXPORT void JNICALL Java_testJNI_FonctionsString_ecrisString (JNIEnv *, jclass, jstring); /* * Class: testjni_fonctionsstring * Method: recuperestring * Signature: ()Ljava/lang/String; */ JNIEXPORT jstring JNICALL Java_testJNI_FonctionsString_recupereString (JNIEnv *, jclass); Etape 3 : Ecriture du code C++ : L'ecriture du code C++ va demander cette fois l'utilisation de methodes fournies pas la JNI. Comme precisé precedement, une String est un objet qui neccessite plusieurs etapes pour etre utilisé. Tout d'abord il est neccessaire cette fois de nommer l'environnement JNI qui nous permettra ainsi d'appeller des fonctions de l'api. Dans notre exemple, nous le nomeront env, ce qui sera son nom par defaut durant le reste de ce document (La signification precise de JNIEnv et de jclass sera etudiée plus tard). Lorsque la fonction recoit la chaine en parametre, il est neccessaire de la convertir en chaine java. Pour cela l'environnement JNI fourni une fonction dediée : la methode GetStringUTFChars() peut ainsi etre utilisée : const char *chainec = env->getstringutfchars(chaine,0); cette methode accepte en parametre la chaine java a convertir ( le second parametre precise si il s'agit d'une copie ou d'un accés à la chaine originale).

On peut donc ecrire les methodes C++ suivantes : #include "testjni_fonctionsstring.h" #include <iostream> JNIEXPORT void JNICALL Java_testJNI_FonctionsString_ecrisString (JNIEnv *env, jclass, jstring chaine) // recuperation de la chaine passée en parametre const char *chainec = env->getstringutfchars(chaine,0); // on ecris a l'ecran la chaine printf(chainec); // on indique que le C n'a plus besoin de la chaine env->releasestringutfchars(chaine,chainec); JNIEXPORT jstring JNICALL Java_testJNI_FonctionsString_recupereString (JNIEnv *env, jclass) // Construction d'une chaîne Java à partir d'une chaîne C++ return env->newstringutf("chaine venant du code C"); comme le montre l'exemple, lorsque l'on utilise une chaine java, il est neccessaire de garder à l'esprit qu'il est obligatoire pour des raisons de gestions memoire de preciser à la fin des traitements que l'objet String n'est plus utilisé. Dans le cas contraire, le ramasse miette ne sera pas en mesure de liberer l'espace memoire ainsi alloué. La creation d'une String java, quand à elle, est assez simple, il suffit d'invoquer la methode NewStingUTF avec comme parametre la chainec a convertir. Il existe diverses autres methodes permettant de travailler sur des chaines dans le cadre des methodes natives. Voici la liste de ces fonctions avec le lien vers la reference SUN concernée. fonctions d'utilisation : NewString GetStringLength GetStringChars ReleaseStringChars NewStringUTF GetStringUTFLength GetStringUTFChars ReleaseStringUTFChars GetStringRegion GetStringUTFRegion GetStringCritical Release StringCritical comme l'indiquent leurs noms, ces methodes permettent de recuperer les tailles, une partie de chaine, de les créer et de les implementer dans un environnment multithread.

4 \ utilisation de tableaux avec les methodes natives. Au meme titre que les chaines de caracteres, les tableaux en java sont en fait des objets. Il existe alors des methodes destinées a leur utilisation dans des methodes natives cependant avant de regarder un exemple, il est neccessaire de comprendre le fonctionnement interne de la machine virtuelle java en ce qui concerne les tableaux. Pour chaque type natif, java defini un tableau, il existe donc huit tableaux natifs plus un pour les tableaux d'objets. L'interface JNI fourni donc un double des fonctions pour chacun de ces types de tableaux. le tableau suivant donne la correspondance entre le type de tableau voulu et la methode correspondante à utiliser pour les créer. NewBooleanArray() NewByteArray() NewCharArray() NewShortArray() NewIntArray() NewLongArray() NewFloatArray() NewDoubleArray() jbooleanarray jbytearray jchararray jshortarray jintarray jlongarray jfloatarray jdoublearray

Etape 1 : declaration des methodes en java : L'exemple suivant montre juste comment ecrire deux fonctions, l'une renvoyant un tableau, l'autre l'utilisant : package testjni; public class FonctionsTableau static System.loadLibrary("testJNI_FonctionsTableau"); private static native void printtableau(int [] tableau); public static native int [] gettableau(); public static void main(string[] args) // recupere un tableau int [] montableau = gettableau(); // imprime le tableau printtableau(montableau); Etape 2 : Generation du fichier d'entete C++ : /* DO NOT EDIT THIS FILE - it is machine generated */ #include <jni.h> /* Header for class testjni_fonctionstableau */ #ifndef _Included_testJNI_FonctionsTableau #define _Included_testJNI_FonctionsTableau extern "C" /* * Class: testjni_fonctionstableau * Method: printtableau * Signature: ([I)V */ JNIEXPORT void JNICALL Java_testJNI_FonctionsTableau_printTableau (JNIEnv *, jclass, jintarray); /* * Class: testjni_fonctionstableau * Method: gettableau * Signature: ()[I */ JNIEXPORT jintarray JNICALL Java_testJNI_FonctionsTableau_getTableau (JNIEnv *, jclass);

Etape 3 : Ecriture du code C++ : comme precisé auparavant, il est neccessaire d'utiliser une methode par type de tableau. Dans notre cas, nous utiliserons des tableaux d'int, ce qui nous poussera à utiliser les methodes dediées. Pour changer le type de données contenu dans le tableau, il suffit de changer dans le prototype de la methode int par le type choisi. #include "testjni_fonctionstableau.h" #include <iostream> JNIEXPORT void JNICALL Java_testJNI_FonctionsTableau_printTableau (JNIEnv *env, jclass, jintarray montableau) // longueur du tableau jsize longueur = env->getarraylength(montableau); // Création d'un tableau C++ de valeur entière jint *tableauc = env->getintarrayelements(montableau,0); // impression du tableau for(int i=0;i<longueur;i++) printf("valeur a l'indice %d est egale a :%d\n",i,longueur); // on precise a la VM que le code C++ a fini de travailler sur le tableau env->releaseintarrayelements(montableau,tableauc,0); JNIEXPORT jintarray JNICALL Java_testJNI_FonctionsTableau_getTableau (JNIEnv *env, jclass) // on fixe la taille du tableau int taille = 3; // on crée le tableau jintarray montableau = env->newintarray(taille); // on peut ici travailler sur le tableau // on renvoi le tableau return montableau;

Etape 4 : Compilation et Execution : à l'execution le programme donne le résultat suivant : valeur a l'indice 0 est egale a:3 valeur a l'indice 1 est egale a:3 valeur a l'indice 2 est egale a:3 Note : la methode newintarray crée un tableau dont chacune des valeurs est initialisée pour contenir la taille, ou dans le cas d'un tableau d'objet, des pointeurs nulls. Les fonctions suivantes permettent d'utiliser les tableaux java. Chacune des methodes ici, est un lien vers la reference SUN correspondante. GetArrayLength NewObjectArray GetObjectArrayElement SetObjectArrayElement New<PrimitiveType>Array Routines Get<PrimitiveType>ArrayElements Routines Release<PrimitiveType>ArrayElements Routines Get<PrimitiveType>ArrayRegion Routines Set<PrimitiveType>ArrayRegion Routines GetPrimitiveArrayCritical ReleasePrimitiveArrayCritical 5 \ conclusion: ce document nous a permis de voir comment cette fois de passer des variables simples entre java et ses methodes natives. Il est donc maintenant possible de commencer à ecrire des methodes reellement utilisables, mais laisse cependant un trou pour le prochain document : l'utilisation de methodes d'instance d'objets java à partir du code natif C++ ouvrant ainsi la voix au debut de la programmation objet.