Récemment, j’ai eu l’occasion de travailler sur un wrapper JNI que l’on utilise dans le projet Lithium pour appeler du Java à partir du C++. Non seulement est-ce que j’ai été satisfait du résultat que ça a donné, mais j’ai eu un plaisir fou à le réaliser. Aujourd’hui, je veux partager ce thrill avec vous.
Voici le chapitre sur les pointeurs et les références en C++.
Si vous avez des remarques ou suggestions afin de le parfaire.
N’hésitez pas à me contacter via mon email:
pr.azizdarouichi@gmail.com.
Bonne lecture.
Voici le chapitre sur les fonctions en C++.
La nouvelle version 2019 est par là:
https://fr.slideshare.net/AzizDarouichi/chapitre2fonctionscppv2019
Si vous avez des remarques ou suggestions afin de le parfaire.
N’hésitez pas à me contacter via mon email:
pr.azizdarouichi@gmail.com.
Cours en C++ de la programmation procédurale à la POO.
Partie 1: La Programmation Procédurale.
Partie 2: La Programmation Orientée Objet.
Partie 3: Les Exceptions, Entrées/Sorties, Structures, Unions, Énumérations…
Partie 4: Les interfaces Graphiques avec Qt.
Si vous avez des remarques ou des suggestions afin d'améliorer ce support du cours merci de me contacter via pr.azizdarouichi@gmail.com
Voici la nouvelle version 2019 du chapitre sur les fonctions en C++:
https://fr.slideshare.net/AzizDarouichi/chap2fonctionscpp
Si vous avez des remarques ou suggestions afin de le parfaire.
N’hésitez pas à me contacter via mon email:
pr.azizdarouichi@gmail.com.
C'est le premier chapitre du cours en C++ de la programmation procédurale à la POO.
Partie 1: La Programmation Procédurale.
Partie 2: La Programmation Orientée Objet.
Partie 3: Les Exceptions, Entrées/Sorties, Structures, Unions, Énumérations…
Partie 4: Les interfaces Graphiques avec Qt.
C'est la version 2019 du chapitre 1 sur C++:
https://fr.slideshare.net/AzizDarouichi/chap1-cours-en-c
Si vous avez des remarques ou des suggestions afin d'améliorer ce support du cours merci de me contacter via pr.azizdarouichi@gmail.com
Bonne lecture
Voici le chapitre 6 sur les classes et les interfaces en Java.
Si vous avez des remarques ou suggestions afin de le parfaire.
N’hésitez pas à me contacter via mon email:
pr.azizdarouichi@gmail.com.
Bonne lecture.
C'est le chapitre 1 sur le langage Python qui est une introduction à ce langage.
Si vous avez des remarques ou des suggestions pour l’améliorer n’hésitez pas à m’écrire via ce courriel:
pr.azizdarouichi@gmail.com
Bonne lecture.
Voici le chapitre sur les pointeurs et les références en C++.
Si vous avez des remarques ou suggestions afin de le parfaire.
N’hésitez pas à me contacter via mon email:
pr.azizdarouichi@gmail.com.
Bonne lecture.
Voici le chapitre sur les fonctions en C++.
La nouvelle version 2019 est par là:
https://fr.slideshare.net/AzizDarouichi/chapitre2fonctionscppv2019
Si vous avez des remarques ou suggestions afin de le parfaire.
N’hésitez pas à me contacter via mon email:
pr.azizdarouichi@gmail.com.
Cours en C++ de la programmation procédurale à la POO.
Partie 1: La Programmation Procédurale.
Partie 2: La Programmation Orientée Objet.
Partie 3: Les Exceptions, Entrées/Sorties, Structures, Unions, Énumérations…
Partie 4: Les interfaces Graphiques avec Qt.
Si vous avez des remarques ou des suggestions afin d'améliorer ce support du cours merci de me contacter via pr.azizdarouichi@gmail.com
Voici la nouvelle version 2019 du chapitre sur les fonctions en C++:
https://fr.slideshare.net/AzizDarouichi/chap2fonctionscpp
Si vous avez des remarques ou suggestions afin de le parfaire.
N’hésitez pas à me contacter via mon email:
pr.azizdarouichi@gmail.com.
C'est le premier chapitre du cours en C++ de la programmation procédurale à la POO.
Partie 1: La Programmation Procédurale.
Partie 2: La Programmation Orientée Objet.
Partie 3: Les Exceptions, Entrées/Sorties, Structures, Unions, Énumérations…
Partie 4: Les interfaces Graphiques avec Qt.
C'est la version 2019 du chapitre 1 sur C++:
https://fr.slideshare.net/AzizDarouichi/chap1-cours-en-c
Si vous avez des remarques ou des suggestions afin d'améliorer ce support du cours merci de me contacter via pr.azizdarouichi@gmail.com
Bonne lecture
Voici le chapitre 6 sur les classes et les interfaces en Java.
Si vous avez des remarques ou suggestions afin de le parfaire.
N’hésitez pas à me contacter via mon email:
pr.azizdarouichi@gmail.com.
Bonne lecture.
C'est le chapitre 1 sur le langage Python qui est une introduction à ce langage.
Si vous avez des remarques ou des suggestions pour l’améliorer n’hésitez pas à m’écrire via ce courriel:
pr.azizdarouichi@gmail.com
Bonne lecture.
Voici le chapitre sur les classes et les objets en C++.
Si vous avez des remarques ou suggestions afin de le parfaire.
N’hésitez pas à me contacter via mon email:
pr.azizdarouichi@gmail.com.
Bonne lecture.
Chapitre 11: Expression Lambda et Référence de méthode en JavaAziz Darouichi
Voici le chapitre 11 sur les expressions lambda et les références de méthodes en Java.
Si vous avez des remarques ou suggestions afin de le parfaire.
N’hésitez pas à me contacter via mon email:
pr.azizdarouichi@gmail.com.
Bonne lecture.
Voici le chapitre sur la surcharge des opérateurs en C++.
Si vous avez des remarques ou suggestions afin de le parfaire.
N’hésitez pas à me contacter via mon email:
pr.azizdarouichi@gmail.com.
Bonne lecture
Cette diapositive présente l'essentiel de langage C# pour des personnes qui'ont deja des notions en POO, dans cette présentation on traite les bases de C# comme les variables, les boucles, les classes, les exception, et aussi on traite des concepts avancés comme les delegates et les événements.
Comme des millions de développeurs, vous utilisez C# quotidiennement … mais en maitrisez-vous les subtilités ? Cette session ludique vous plongera au cœur de votre langage de prédilection au travers programmes et exemples de code qui ne cesseront de vous surprendre. Avec en prime quelques (petits) lots à gagner pour les développeurs les plus perspicaces !
Formation C# - Cours 2 - Programmation procéduralekemenaran
Deuxième partie de la formation C# du Club Microsoft Isep. Types de données, structures conditionnelles, structure de contrôle, utilisation de la console.
Les nouveautés de C++11 : Ecrire du C++ ModerneMicrosoft
Le langage C++ a toujours la réputation d’un langage complexe, demandant une rigueur de tous les instants et qui peut en rebuter plus d’un. Mais avec l’arrivée de la nouvelle norme C++11 et de son intégration dans Visual Studio 11 (et intégration partielle dans Visual Studio 2010), elle permet comme le souligne Herb Sutter, d’écrire désormais du code "Clean, Safe and Fast", nous passons à l'ère du C++ moderne.
Articulé autour de C++ 11, cette session amène celui qui y assiste aux fondamentaux du développement logiciel : libraries, dépendances, TR1 et C++0X les fondations de C++ 11, runtime C alias CRT, runtime C++ alias STL, agilité en C++, ALM en C++, Windows 8 et C++, C++ et Windows 8 avec le nouveau modèle COM nommé WRL.
Notions de base de programmation en langage C, le syntaxe, les opérateurs, l'affichage et le saisie, les structures de contrôle, les boucles.
cours par Benouini Rachid.
Voici le chapitre sur les classes et les objets en C++.
Si vous avez des remarques ou suggestions afin de le parfaire.
N’hésitez pas à me contacter via mon email:
pr.azizdarouichi@gmail.com.
Bonne lecture.
Chapitre 11: Expression Lambda et Référence de méthode en JavaAziz Darouichi
Voici le chapitre 11 sur les expressions lambda et les références de méthodes en Java.
Si vous avez des remarques ou suggestions afin de le parfaire.
N’hésitez pas à me contacter via mon email:
pr.azizdarouichi@gmail.com.
Bonne lecture.
Voici le chapitre sur la surcharge des opérateurs en C++.
Si vous avez des remarques ou suggestions afin de le parfaire.
N’hésitez pas à me contacter via mon email:
pr.azizdarouichi@gmail.com.
Bonne lecture
Cette diapositive présente l'essentiel de langage C# pour des personnes qui'ont deja des notions en POO, dans cette présentation on traite les bases de C# comme les variables, les boucles, les classes, les exception, et aussi on traite des concepts avancés comme les delegates et les événements.
Comme des millions de développeurs, vous utilisez C# quotidiennement … mais en maitrisez-vous les subtilités ? Cette session ludique vous plongera au cœur de votre langage de prédilection au travers programmes et exemples de code qui ne cesseront de vous surprendre. Avec en prime quelques (petits) lots à gagner pour les développeurs les plus perspicaces !
Formation C# - Cours 2 - Programmation procéduralekemenaran
Deuxième partie de la formation C# du Club Microsoft Isep. Types de données, structures conditionnelles, structure de contrôle, utilisation de la console.
Les nouveautés de C++11 : Ecrire du C++ ModerneMicrosoft
Le langage C++ a toujours la réputation d’un langage complexe, demandant une rigueur de tous les instants et qui peut en rebuter plus d’un. Mais avec l’arrivée de la nouvelle norme C++11 et de son intégration dans Visual Studio 11 (et intégration partielle dans Visual Studio 2010), elle permet comme le souligne Herb Sutter, d’écrire désormais du code "Clean, Safe and Fast", nous passons à l'ère du C++ moderne.
Articulé autour de C++ 11, cette session amène celui qui y assiste aux fondamentaux du développement logiciel : libraries, dépendances, TR1 et C++0X les fondations de C++ 11, runtime C alias CRT, runtime C++ alias STL, agilité en C++, ALM en C++, Windows 8 et C++, C++ et Windows 8 avec le nouveau modèle COM nommé WRL.
Notions de base de programmation en langage C, le syntaxe, les opérateurs, l'affichage et le saisie, les structures de contrôle, les boucles.
cours par Benouini Rachid.
Swift est désormais open source ! "Google considérerait Swift comme un langage « de première classe » pour Android" pouvait-on lire en avril sur le réseau. Et enfin un portage Android du langage a été "merge" dans la base de code officielle de Swift.
Bon tout ceci est un bon prétexte pour apprendre ce nouveau langage et les possibilités qu'il peut nous apporter en terme de développement. Une comparaison avec Java sera notamment proposée afin de montrer les similitudes et differences entre ces deux langages .
Les compilateurs nous ennuient tous les jours avec des messages d'erreurs en chinois... alors qu'ils ne font que leur travail, et souvent le font à la perfection ;-)
(Re)découvrez comment les compilateurs fonctionnent en interne et ainsi à devenir plus indulgent à leur égard.
Support Dot Net avec C#. Ce cours traite les points suivants :
- Architecture .Net
- Les bases de C#
- Objet et Classe
- Héritage
- Encapsulation
- Polymorphisme
- Les exceptions
- Les entrées sorties
- Les interfaces graphiques
- Le multi Threading
- Programmation réseaux (Sockets et DataGram)
- Accès aux bases de données
IMPLEMENTATION EN PYTHON DES CONVENTIONS ALGORITHMIQUES (2022-2023)Tunisie collège
Ministère de l’Éducation de Tunisie
Direction Générale des Programmes
et de la Formation Continue
Le langage de programmation choisi pour implémenter les solutions algorithmiques est le
langage de programmation Python.
Cours C Avancé chapitre 2 et chapitre.pdfc79024186
Ce pdf permet d'avoir des connaissances vagues sur le langage de programmation C, ce qui pourrait s'avérer nécessairement de nos jours. Plusieurs points seront utilisés dans ce document.
4. JNI (Java to Native Interface)
Java
C, C++,
C#,Fortran,
Haskell
(n’importe quel
language qui
supporte la C
calling
convention)
5. Exemple (Java)
class JniTest
{
/**
Implemented in c++
*/
native boolean nativeMethod(String s);
/**
Called from c++
*/
void javaMethod(int i, float f) {
System.out.println("Hello from native!");
}
static void main(String args) {
new JniTest().nativeMethod("Ni!");
}
static {
System.loadLibrary("MyNativeLibrary");
}
}
6. Exemple (C++)
JNIEXPORT jboolean JNICALL Java_JniTest_nativeMethod
(JNIEnv* env, jobject obj, jstring s)
{
std::cout << env->GetStringUTFChars(s,0) << std::endl;
jclass clazz = env->FindClass("JniTest");
jmethodID m = env->GetMethodID(clazz, “javaMethod", "(ID)V");
std::thread([=]
{
env->CallStaticObjectMethod(clazz, m, 42, "1.0", 3.14);
}).detach();
return JNI_TRUE;
}
Voyez-vous un bug ?
Et pourtant, ce code compile sans erreur et sans warning!
7. Solutions existantes
Générateurs de code
GIWS
JACE
Codemesh JunC++ion
Wrapper + générateur
android-cpp-sdk
Autres (appel de code natif à partir de Java)
SWIG
JNIWrapper
8. L’objectif
Sans générateur de code
Sans fichier de configuration
Sans code d’initialisation
Sans gras trans
myClass.invoke<void(jint, jfloat)>("javaMethod", 42, 1.0);
Type de la function
Sert à générer la signature JNI
ET à valider la liste des
arguments
Les arguments passés à
la fonction
Le nombre et les types sont
validés à la compilation
Le nom de la
méthode Java
Lance une exception si
elle n’existe pas
9. Plan de match
1. Génération de la signature JNI (“(IF)V”)
2. Interface d’invocation (invoke())
3. Invocation (env->CallStaticVoidMethod())
10. Génération de la signature
Projeter (mapper) un type en string
jint -> "I"
(type) (string)
Décomposition du function type
void(jint,jfloat) -> Ret = void
P1 = jint
P2 = jfloat
Bâtir la signature
void(jint, jfloat) -> "(IF)V"
11. Projeter un type en string
Solution: TypeTrait
template<class T>
struct JniTypeTrait;
template<> struct JniTypeTrait<jfloat>
{
static const char* signature() {return "F";}
};
template<> struct JniTypeTrait<jint>
{
static const char* signature() {return "I";}
};
// Exemple
const char* signature_int = JniTypeTrait<jint>::signature();
template<> struct JniTypeTrait<void>
{
static const char* signature() {return "V";}
};
// …ainsi de suite pour les autres types
12. Décomposition du fonction type
Des meta-fonctions ??? Une liste de types ???
typedef boost::mpl::at_c<ParameterTypes, 0>::type P1;
typedef boost::mpl::at_c<ParameterTypes, 1>::type P2;
typedef boost::function_types::parameter_types<F>::type ParameterTypes;
typedef boost::function_types::result_type<F>::type ReturnType;
typedef void(F)(jint, jfloat);
13. Template Metaprogramming
Effectuer des calculs par à la compilation
Les calculs se basent sur des types et des
constantes
Le résultat est une constante ou du code
Turing Complete!
Possible d’effectuer n’importe quelle computation
Pas de variable!
Pas de loops. Seulement de la récursion.
Familiarité avec le paradigme fonctionnel
16. Function Type to JNI Signature
std::string buf;
buf += "(";
buf += ")";
buf += JniTypeTrait<ReturnType>::signature();
[&] (auto t) {
buf += JniTypeTrait<decltype(t)>::signature();
}
boost::mpl::for_each<ParameterTypes>(
);
NB: Les polymorphic lambdas (avec auto) ont été introduits dans
C++14 (qui est actuellement en cours de standardisation). Ils sont
disponibles dansVS2013 CTP, GCC 4.9 et Clang 3.4
18. Invocation (interface)
Rappel de l’enjeux:Vérification compile-time
du nombre et du type des arguments
obj.invoke<void(jint, jfloat)>("func", 1); // Error!
obj.invoke<void(jint, jfloat)>("func", 1, 2.0, 3); // Error!
obj.invoke<void(jint, jfloat)>("func", "1", "2.0"); // Error!
obj.invoke<void(jint, jfloat)>("func", 1, 1.0); // OK
20. Question quiz
Sachant que boost::mpl::at_c<Seq, n> n’est
valide que pour des valeurs de n comprise entre 0
et boost::mpl::size<Seq>::value,
Comment se peut-il y avoir des overloads de
invoke() pour chaque nombre d’arguments sans
erreur de compilation ?
typedef boost::mpl::vector<int> TypeList;
typedef boost::mpl::at_c<TypeList, 2>::type foo; // Error!
21. Réponse: SFINAE
Substitution Failure Is Not An Error
If an invalid argument or return type is formed during the instantiation
of a function template, the instantiation is removed from the overload
resolution set instead of causing a compilation error.
http://boost.org/doc/libs/1_55_0/libs/utility/enable_if.html
Exemple:
int negate(int i) {
return -i;
}
template<class F>
typename F::result_type negate(const F& f) {
return -f();
}
24. Invocation (implementation)
OK, mais ce n’est pas tout!
CallIntMethod()
Et si ReturnType vaut autre
chose que jint ??
auto r = env_->CallIntMethod(object_, method, p1);
env_.checkException();
return r;
25. Invocation (variations sur ReturnType)
typedef JniTypeTrait<typename JniMethod<F>::ReturnType> Trait;
((*env_).*Trait::callFunction())
// pointer-to-member-function type (to simplify callFunction() declaration)
typedef jint (JNIEnv::*CallFunctionType)(jobject, jmethodID, ...);
// return the JNIEnv member function to call to return jint
static CallFunctionType callFunction() {return &JNIEnv::CallIntMethod;}
26. Invocation (cas de ReturnType=void)
Il reste un problème:
auto r = env_->CallVoidMethod(object_, method, p1);
>> ERROR! auto cannot deduce type from void
27. Invocation (cas de ReturnType=void)
template<class ReturnType, class ParameterTypes>
struct Invoker
{
ReturnType operator()()
{
auto r = ((*env_).*CallFunc_)(object_, method_);
env_.checkException();
return r;
}
};
template<class ParameterTypes>
struct Invoker<void, ParameterTypes>
{
void operator()()
{
env_->CallVoidMethod(object_, method_);
env_.checkException();
}
}; Et les paramètres dans tout ça ?
30. Voilà!
Autres fonctionnalités:
Gestion des références (locales vs globales)
Gestion des exceptions
Scope de fonction et de thread
Facilitateur pour les Strings
Surveillez les commits dans Lithium
(git@git.innobec.com:innobec/lithium.git)
obj.invoke<void(jint, jfloat)>("javaMethod", 42, 1.0);
Récemment, j’ai eu l’occasion de travailler sur un wrapper JNI que l’on utilise dans le projet Lithium pour appeler du Java à partir du C++. Non seulement est-ce que j’ai été satisfait du résultat que ça a donné, mais j’ai eu un plaisir fou à le réaliser. Aujourd’hui, je veux partager ce thrill avec vous.
Cette présentation n’est pas une présentation exhaustive du wrapper JNI. Il s’agit plutôt d’un survol partiel avec emphase sur le “comment ça marche” et un prétexte pour présenter certaines technique moderne de programmation c++ qui sont inconnue à plusieurs.
SVP éviter les questions du genre “pourquoi ne pas faire ceci au lieu de cela ?”, qui pourrait faire diverger rapidement la présentation déjà chargée. Je suis disponible pour en parler par après. Tous les commentaires et questions sont d’ailleurs les bienvenus.
JNI permet d’appeler du code natif à partir du Java et appeler du code Java à partir du code C++.
Le premier cas d’utilisation est plus fréquent et plus simple. Il permet à des organisations de rentabiliser un code base natif et l’intégrant à une application moderne Java.
Le second cas est plus rare (parce qu’en général non requis dans le premier cas d’utilisation) et aussi plus compliqué à cause de l’aspect “managed” de la JVM.
La fonction “nativeMethod” est implémentée par du code natif.
La fonction “javaMethod” est appelée par le code natif.
La signature de la fonction est générée par l’outil “javah” qui est inclus avec le JRE.
Il ne reste plus qu’à remplir le corps de la fonction et compiler. Exemples typiques:
Accéder le tableau de caractères d’une string Java
Charger une classe par son nom
Récupérer la méthode à appeler, identifiée par son nom et par sa signature
Appeler la méthode
Mais il y a des bugs dans cet exemple:
Leak de mémoire de la string UTF8
Erreur dans la signature
Erreur dans le nombre et le type des arguments
Mauvaise fonction d’appel (static + return type)
Initialization de l’environnement JNI pour les threads
Passage illégal de l’environnement et des références entre threads
Gestion d’erreurs
La majorité des solutions existantes comporte un générateur de code. C’est bien, mais c’est lourd, surtout dans un petit projet si l’on a qu’un ou deux appels à faire (on se connait: en tant que développeur, on va le faire manuellement plutôt que sortir la grosse machine.)
Voici l’objectif:
Syntaxe succinte, claire et simple
Pur C++
Sure (vérification statique) + exception en cas d’erreur runtime
Sondage:
Piece of cake ?
Possible, mais ne sait pas trop comment ?
What?
Si vous avez répondu b), cette présentation est pour vous!!
Pour cette présentation, je me limite seulement à l’aspect “appel d’une méthode Java en C++”. Il y a d’autres aspects, mais il faut faire des choix.
On commence en douceur…
On définit une classe “JniTypeTrait” pour laquelle on fournit une spécialisation pour int, float, void, etc.
La fonction membre signature() permet d’obtenir la string correspondant au type.
Simple, non ?
Ensuite, il faut extraire les types de la signature de la fonction
Boost.FunctionTypes offre des méta-fonctions qui permettent d’extraire le ReturnType et le type des arguments sont la forme d’une liste de type.
Boost.MPL permet ensuite d’extraire le type de chaque paramètre à partir de la liste avec la méta-fonction at_c<>
Le TMP a été “découvert accidentellement” durant la standardisation du c++. On réalise alors que non seulement on peut faire plein de chose avec les templates, mais qu’on peut faire n’importe quel calcul! (Turing complete-ness).
Comme le langage n’a pas été concu pour ça, la syntaxe est plus bizarre, mais on s’habitue.
Il y a 10 ans, les compilateurs suffoquaient à compiler des meta-programme moindrement complexe. Aujourd’hui, ce n’est plus un problème et l’évolution du langage fait de plus en plus de place à la métaprogrammation.
Tout le monde connait la suite de Fibonacci, alors on va l’implémenter dans un métaprogramme!
Cette façon de faire dite “pattern matching” est typique des langages fonctionnels.
La limitation: les arguments et le résultats sont des constantes à la compilation.
Boost.MPL fournit un algorithme, for_each, qui, comme son pendant STL, invoque un functor pour chaque élément d’une séquence. À la différence que la séquence en question est, dans le cas mpl::for_each, une séquence de types.
Convertir un type en string? Nous avons déjà vu ça! JniTypeTrait ! Trop facile…
Troisième et dernière étape de notre périple…
Voici la solution pour ReturnType=int. Rien de compliqué
La fonction checkException() vérifie qui une exception Java a été lancée et convertie celle-ci en exception C++. On se rappele que JNI est une API C et donc ne supporte pas les exceptions nativement. Les exceptions Java sont donc émulées par des attributs de JNIEnv que le programmeur se doit de vérifier.
On ramène la class de Trait définit plus tôt et on y ajoute une fonction qui permet d’obtenir la fonction JNI à appeler selon le type de valeur de retour. La fonction est retournée sous la forme d’un pointeur vers une fonction membre (dont un typedef est déclaré pour fin de lisibilité).
Impossible, même pour auto, de déclarer une variable de type void (qui, par définition, signifie absence de type)
Dans un premier temps, on refactor le corps de la fonction dans une classe “invoker”
NB: cette définition est complète: il manque le constructeur ainsi que les membres
Dans un 2e temps, on crée une spécialisation partielle pour ReturnType=void
Pas de spécialisation partielle des function templates
Ici, on peut se permettre d’accepter n’importe quoi parce que la validation a été faite au niveau de invoke()
Alors, on utilise simplement un variadic template
Voici un exemple type d’utilisation de variadic templates
L’équivalent de la fonction print en Python.
Il ne faut pas confondre les variadic templates (…) et les VARARGS (…). Les derniers ne sont pas sécuritaires et un héritage du langage C. Les variadic templates, en revanches, sont sécuritaires parce qu’ils n’existent qu’à la compilation.
À noter:
Le template parameter pack n’est pas un type! Il n’est pas manipulable au runtime. En fait, comme les templates, il n’existent carrément plus une fois le programme compilé…
Il est possible d’inclure une expression abitrairement complexe dans l’expansion du pack.