""
""
Essaie comme ceci:
Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 //Factory.cpp #include <string> #include "Factory.h" #include "MyQt.h" extern "C" DYNAMIQUE_API LibraryInterface* createInstance() { return (new MyQt()); } extern "C" DYNAMIQUE_API void deleteInstance(LibraryInterface *instance) { delete instance; }
Code C++ : 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 #include <windows.h> #include <iostream> #include "LibraryInterface.h" using namespace std; typedef LibraryInterface* (*POINTEUR_FONCTION) (void); int main(int &argc, char **argv) { HINSTANCE DllInstance; POINTEUR_FONCTION createInstance = NULL; if ((DllInstance=LoadLibrary(TEXT("DllLibrary.dll")))!=NULL) { cout << "Load" << endl; createInstance = (POINTEUR_FONCTION)::GetProcAddress(DllInstance, "createInstance"); if (createInstance != NULL) { cout << "Fonction Load" << endl; LibraryInterface *pMyQt; cout << pMyQt << endl; pMyQt= createInstance(); cout << pMyQt << endl; pMyQt->createWindow(); } else { cout << "Fonction unload" << endl; } //On libère la dll FreeLibrary(DllInstance); }else{ cout << "Unload" << endl; } char pause; cin >> pause; return 0; }
Si "createInstance" n'est toujours pas trouvé, essaie en le précédant d'un underscore dans l'appel à LoadLibrary().
SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.
"Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
Apparently everyone. -- Raymond Chen.
Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.
Il est normal le char* dans
?
Code : Sélectionner tout - Visualiser dans une fenêtre à part typedef LibraryInterface* (*POINTEUR_FONCTION) (char*);
Le manque de portabilité entre compilateur C++ rend l'utilisation d'API C++ complètement illusoire.
Moi, j'utiliserais une API C avec un void* (un handler) comme premier paramètre qui sera un pointeur sur l'objet.
Résultats :
un complète compatibilité avec tout les compilateurs C/C++,
cloisonnement strict entre les C-Runtime das Dll,
utilisation par des languages non-objet
utilisation de la POO via le handle ( à la Win32)
Rien n'empêche de créer des DLLs cantonnées à un seul projet, tu sais...
De plus, ensuite il y a des standards pour une meilleure portabilité au niveau objet, sous certains systèmes. Sous Windows, il y a COM (Component Object Model), qui marchera quel que soit le compilateur du moment qu'on respecte ses guidelines.
SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.
"Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
Apparently everyone. -- Raymond Chen.
Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.
Une API COM est une API "Objet" language agnostique, et pas C++.
Déjà qu'ils ont du mal à gérer des types simples, imagine avec les types template pour la gestion de la durée de vie des références.
Une dll pour 1 projet, autant pas faire de dll. les dll sont faite pour être partagées et évolutives, sinon autant faire des librairies statiques.
On peut toujours les partager entre plusieurs exécutables d'un même projet. C'est le cas à mon boulot, d'ailleurs.
SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.
"Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
Apparently everyone. -- Raymond Chen.
Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.
A part obliger tous les exécutable à avoir les mêmes compilateurs et options de compilation ou encore d'être obligé de faire des compromis dans les configurations d'optimisations, je n'y vous aucun intérêt à part une très hypothétique diminution de taille de l'exécutable qui ne compensera pas le manque de performance au démarrage dû aux compromis d'optimisations.
Donc, à part pour montrer que c'est faisable dans un tout petit périmètre sans grands intérêts, à mon avis, cela ne sert qu'à faire trimer les débutants sur une voix sans issue.
Facile quand tous les exécutables sont dans le même projet...
Je ne vois pas ce que tu veux dire pour "compromis d'optimisations"...ou encore d'être obligé de faire des compromis dans les configurations d'optimisations, je n'y vous aucun intérêt à part une très hypothétique diminution de taille de l'exécutable qui ne compensera pas le manque de performance au démarrage dû aux compromis d'optimisations.
Là, je suis d'accord, le périmètre est petit, et ça n'est pas d'un grand intéret pour les débutants. La plupart du temps, si on veut un composant réutilisable en C++, autant le programmer directement en COM.Donc, à part pour montrer que c'est faisable dans un tout petit périmètre sans grands intérêts, à mon avis, cela ne sert qu'à faire trimer les débutants sur une voix sans issue.
PS: Le projet sur lequel on bosse à mon boulot est basé sur MFC, contient 90 "projets" Visual 6, dont la moitié des applications. Ici, le code est correctement factorisé et réutilisé. Mais quand ça n'atteint pas cette échelle, on peut se limiter aux templates et bibliothèques statiques...
SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.
"Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
Apparently everyone. -- Raymond Chen.
Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.
Je pense donc que nous sommes d'accord sur le fait que lesnakman ne devrait pas tenter de faire une API C++.
Pas si facile si nous avons beaucoup de projets dans une solution et que toute ou partie de la solution doit utiliser une nouvelle version du compilateur.Facile quand tous les exécutables sont dans le même projet...
A moins d'être bloqué ad vitam aeternam sur une version antédiluvienne de VC6.
Quand on pousse assez loin l'optimisation, on cherche à rapprocher, grâce au profiling, les codes utilisés ensemble, donc plus il y a d'appelants, plus la probabilité d’avoir du code utilisés ensemble par tous les appelants est faible. Il faut faire des compromis pour que tous les appelant est une bonne performance mais pas la meilleur possible pour l'un des appelant. Chose que l'on peut faire pour chaque lib de chaque projet et nom sur les dll partagé par plusieurs projets.Je ne vois pas ce que tu veux dire pour "compromis d'optimisations"...
C'est justement qu'en ça atteint une certaine échelle qu'il ne faut pas être lié trop intimement avec le compilateur, pour pouvoir suivre l'évolution du compilateur par exemple.Mais quand ça n'atteint pas cette échelle, on peut se limiter aux templates et bibliothèques statiques...
Oui, nous sommes d'accord.
En fait, on a porté toute la solution de VC++6 à VS2005 sans problème.
Mais on n'a pas fait d'optimisation cross-module (ni même de LTCG, c'est une honte).
SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.
"Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
Apparently everyone. -- Raymond Chen.
Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.
concernant le typedef LibraryInterface* (*POINTEUR_FONCTION) (char*);
C'était un oubli de ma part, car je compte creer différentes instances par la suite...
Merci pour ces réponses, je vais les lire avec attention.
En faisant un static cast ça marche.
Je suis confronter à un autre problème.
Code : Sélectionner tout - Visualiser dans une fenêtre à part pMyQt= static_cast<MyQt* > ( createInstance() );
Je dois pouvoir créer une fenêtre Qt:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2 QApplication app(argc, argv); return app.exec();
Je dois donc insérer ce code dans ma DLL.(MyQt.cpp)
A partir de visual, comment je peux faire?
Il faut que j'utilise QtCore4.dll et QtGui4.dll. Je croyais qu'en les plaçant QApplication serait reconnu mais ce n'est pas le cas.
Quelqu'un a une idée?
Merci
SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.
"Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
Apparently everyone. -- Raymond Chen.
Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.
Je ne suis pour ma part pas d'accord avec cette idée. Quand on est sur un environnement où il y a suffisamment peu de compilateurs différents pour qu'on puisse :
- Soit faire une version pour tous les compilateurs/options de compilation majeures (sous visual studio, par exemple, seules 2 options posent souvent problème en pratique)
- Soit imposer aux personnes désirant travailler avec nous d'utiliser les mêmes compilateurs avec les mêmes options
- Soit un mix des deux solutions
Définir une API C++ ne pose pas de problèmes particuliers. Après, le choix DLL/lib statique est autre, et j'avoue réserver les DLL principalement aux systèmes de plug-ins.
Les alternatives ont un coût qui n'est pas négligeable pour un projet :
- Obligation de définir un wrapper autour de l'ensemble des classes d'interface, qui plus est dans un langage pas forcément très bien maîtrisé par les équipes, et souvent très basique.
- Difficultés d'utilisation de ce wrapper, justement parce qu'il est défini dans un langage basique qui ne fourni généralement pas de bons outils de gestion de la mémoire, qu'il a un modèle de gestion d'erreur différent du reste du code,...
- Baisse de performances causées par le wrapper, entre autre par la sérialisation/désérialisation de certaines structures de données qu'il demande.
Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.
Heu, mon alternative n'utilise aucun wrapper, est en C, ne propage aucune exceptions, ne definis que des code d'erreur, est compilateur indépendant.
Médinoc...C'est vrai qu'en incluant le MyQt.h , je penses que ça ne respecterais plus le pattern factory.
Si j'ai bien suivi, ta proposition est :
On peut comprendre cette phrase de trois façons :Moi, j'utiliserais une API C avec un void* (un handler) comme premier paramètre qui sera un pointeur sur l'objet.
Soit : Tu as une seule fonction qui ressemble à ce que tu indiques, et de l'autre côté, tu vas caster le void* en quelque-chose qui a plus de sens pour l'utiliser. Dans ce cas, on n'est pas indépendant du compilateur, on doit avoir le même avec les mêmes options des deux côtés, ou une ABI compatible, pour que le cast donne quelque-chose qui a du sens.
Ou bien : Tu as toute une série de fonctions en C prenant un premier paramètre un handler, et qui reprennent grosso-modo l'interface publique de l'objet. Là, on devient indépendant du compilateur, mais cette série de fonction constitue un wrapper, et comme il est écrit en C, il est difficile à utiliser correctement (pas d'argument de type string, mais des char*, par exemple).
Ou bien : L'ensemble de ton programme est en C, et là, d'accord, tu n'es plus dépendant du compilateur, et tu n'as pas écrit de wrapper.
Sur l'aspect "ne propage aucune exception", en est tu certain ? Sais-tu que selon les compilateurs/les options de compilation les exceptions C++ peuvent ou pas être propagées à travers une couche C ? De plus, moi, ce qui m'intéresse, c'est justement que ces exceptions soient propagées. Quand j'ai du code qui wrap du code C++, je passe mon temps à catcher les exceptions dans ce code, générer une erreur selon un mécanisme approprié au wrappeur, et restituer les exceptions de l'autre côté du wrapper.
Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.
Le sens de ma phrase correspond à la deuxième alternative.
La difficulté d'utilisation est toute relative par rapport aux problèmes de gestion des C-Runtimes, mangling etc...
Le "wrapper" est quasi-transparent au niveau performance.
Une bonne interface est une interface avec peu de méthode donc une surcharge de travail assez faible.
L'inclusion de MyQt.h montre bien que le cloisonnement n'est pas maîtrisé et que le résultat sera une jungle inextricable qui s'écroulera à la première dll qui ne respectera des pré-requis mal maîtrisés.
Les exceptions ne sont pas propagées pareil d'un compilateur à l'autre, elles ne sont donc pas censées être autoriser à franchir la barrière d'une DLL portable.
Bien sûr, dans le cas d'une DLL non-portable comme les DLLs d'extensions MFC dans une solution de 90 projets, cette contrainte est relaxée.
SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.
"Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
Apparently everyone. -- Raymond Chen.
Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.
Partager