Précédent   Forum du club des développeurs et IT Pro > C et C++ > C++ > Langage
Langage Langage C++, Programmation Orientée Objet, Templates, etc. Avant de poster : FAQ C++
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse
 
Outils de la discussion
Publicité
'
Vieux 14/12/2012, 21h00   #1
blazed
Nouveau Membre du Club
 
Antoine
Développeur Web
Inscription : octobre 2008
Messages : 66
Détails du profil
Informations personnelles :
Nom : Antoine
Âge : 23
Localisation : France

Informations professionnelles :
Activité : Développeur Web
Secteur : High Tech - Éditeur de logiciels

Informations forums :
Inscription : octobre 2008
Messages : 66
Points : 31
Points : 31
Par défaut Obtenir une instance d'un objet depuis une dll

Bonjour,

je realise un petit projet qui doit charger une dll puis en extraire une instance d'un objet QWidget.

Mon projet charge correctement ma dll de test unitaire et fait correctement fonctionner ma fonction Helloworld. En revanche, il m'est impossible d'obtenir l'objet que je souhaite, ca plante sans message d'erreur.


Je me demande si j'ai choisi la bonne methode?
Est ce qu'il faut lier ma dll aux dlls Qt?


Voici le code de ma library de test :

Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
 
#ifndef		DYNLIB_H_
# define	DYNLIB_H_
 
#ifdef		WIN32
#define	DLEXPORT	__declspec(dllexport)
#define	DLIMPORT	__declspec(dllimport)
#else
#define	DLEXPORT
#define	DLIMPORT
#endif
 
#include	<iostream>
 
#endif	// !DYNLIB_H_
Code :
1
2
3
4
5
6
7
8
9
10
11
12
 
#include "DynLib.h"
 
#include <QWidget>
 
extern "C" void DLEXPORT	helloWorld() {
  std::cout << "Hello World!" << std::endl;
}
 
extern "C" QWidget* DLEXPORT	addonWidget(QWidget* mainWidget) {
  return new QWidget(mainWidget);
}
blazed est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 14/12/2012, 21h53   #2
Klaim
Expert Confirmé
 
Avatar de Klaim
 
Homme Joel Lamotte
Développeur de jeux vidéo
Inscription : août 2004
Messages : 1 555
Détails du profil
Informations personnelles :
Nom : Homme Joel Lamotte
Localisation : France

Informations professionnelles :
Activité : Développeur de jeux vidéo
Secteur : High Tech - Éditeur de logiciels

Informations forums :
Inscription : août 2004
Messages : 1 555
Points : 2 971
Points : 2 971
Code :
1
2
3
extern "C" QWidget* DLEXPORT	addonWidget(QWidget* mainWidget) {
  return new QWidget(mainWidget);
}
extern "C" veux dire que ce qui contiens les accolades, le code est du C. Or ici c'est du C++.

Ce que tu dois faire, c'est avoir une interface C, mais l'implementation est C++. Donc il faut juste separer cela en:

Code :
1
2
3
4
5
6
7
extern "C" { 
 
QWidget* DLEXPORT	addonWidget(QWidget* mainWidget) ; 
 
 // ajouter les autres fonctions a exporter/importer
 
}
Dans le header, puis

Code :
1
2
3
 QWidget* DLEXPORT	addonWidget(QWidget* mainWidget) {
  return new QWidget(mainWidget);
}
Dans le cpp.
Klaim est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 14/12/2012, 22h16   #3
blazed
Nouveau Membre du Club
 
Antoine
Développeur Web
Inscription : octobre 2008
Messages : 66
Détails du profil
Informations personnelles :
Nom : Antoine
Âge : 23
Localisation : France

Informations professionnelles :
Activité : Développeur Web
Secteur : High Tech - Éditeur de logiciels

Informations forums :
Inscription : octobre 2008
Messages : 66
Points : 31
Points : 31
Est ce que tu saurais me dire pourquoi ca fonctionnait avec le helloworld?
blazed est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 15/12/2012, 05h22   #4
koala01
Modérateur
 
Avatar de koala01
 
Philippe Dunski
Inscription : octobre 2004
Messages : 8 628
Détails du profil
Informations personnelles :
Nom : Philippe Dunski
Âge : 41

Informations forums :
Inscription : octobre 2004
Messages : 8 628
Points : 13 351
Points : 13 351
Envoyer un message via MSN à koala01 Envoyer un message via Skype™ à koala01
Salut, Ce n'et qu'un détail, mais bon :
Citation:
Envoyé par blazed Voir le message
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
 
#ifndef		DYNLIB_H_
# define	DYNLIB_H_
 
#ifdef		WIN32
#define	DLEXPORT	__declspec(dllexport)
#define	DLIMPORT	__declspec(dllimport)
#else
#define	DLEXPORT
#define	DLIMPORT
#endif
 
#include	<iostream>
 
#endif	// !DYNLIB_H_
Comme cela, tu devra écrire deux fichiers d'en-tête:
  • un pour compiler ton plugin (qui utilise DLEXPORT) et
  • l'autre pour utiliser ton plugn (qui utilise DLIMPORT)
C'est... dommage, car cela te fait dupliquer du code, parfois important (et doubler ne nombre de fichiers à maintenir)

En plus, si tu utilise DLEXPORT et DLIMPORT dans tes fichiers d'en-tête, si tu as deux bibliothèques dynamiques dont une qui doit utiliser l'autre (après tout, qu'est-ce qui l'empêche ), tu ne saura pas faire la différence entre la compilation de la premiere et celle de la deuxième, et tu risques donc de voir les symboles exportés par la premiere bibliothèque dynamique etre exportés (mais non définis ) par la deuxième.

L'idéal est donc de rajouter la définition d'un symbole préprocesseur à la compilation (comme BUILD_DLLNAME où DLLNAME est peut etre simplement le nom de la bibliothèque) dont la présence permettra de savoir si tu compile ta dll ou si tu l'utilises, et donc d'utiliser le bon symbole au bon moment, grâce à une modification mineure du code

Tu aurais alors quelque chose comme
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#ifndef		DYNLIB_H_
# define	DYNLIB_H_
 
#ifdef		WIN32
#define	DLEXPORT	__declspec(dllexport)
#define	DLIMPORT	__declspec(dllimport)
#else
#define	DLEXPORT
#define	DLIMPORT
#endif
 
#if defined(BUILD_DLLNAME) /* si on compile la dll */
#define DLL_API DLEXPORT /*on utilise DLEXPORT */
#else  /* sinon */
#define DLL_API DLIMPORT /* on uilise DLIMPORT */
#endif
#include	<iostream>
 
#endif	// !DYNLIB_H_
(où DLL_API est unique pour chaque bibliothèque) et, bien sur, de remplacer DLEXPORT par DLL_API partout (ou, au minimum dans les fichiers d'en-tête)
__________________
A méditer: La solution la plus simple est toujours la moins compliquée
Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
Compiler Gcc sous windows avec MinGW
je ne répondrai à aucune question technique par E-mail, message visiteur ou message privé
Vous avez obtenu votre réponse pensez au bouton en bas de page
koala01 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/12/2012, 02h16   #5
blazed
Nouveau Membre du Club
 
Antoine
Développeur Web
Inscription : octobre 2008
Messages : 66
Détails du profil
Informations personnelles :
Nom : Antoine
Âge : 23
Localisation : France

Informations professionnelles :
Activité : Développeur Web
Secteur : High Tech - Éditeur de logiciels

Informations forums :
Inscription : octobre 2008
Messages : 66
Points : 31
Points : 31
@Koala, Merci du conseil.

La solution de Klaim compile belle est bien mais j'arrive toujours a la meme erreure. Losque j'essaie de recuperer l'instance de mon objet QWidget le programme par en succette et ca crash sans message d'erreur particulier.

Ca vous semble pourtant faisable ? Charger une instance de classe d'un objet Qt depuis une dll?

Est ce qu'il faut que l'objet (enfin la class de l'objet) soit configurer pour l'import depuis une dll?
blazed est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/12/2012, 07h46   #6
bretus
Membre expérimenté
 
Ingénieur développement logiciels
Inscription : mars 2009
Messages : 333
Détails du profil
Informations personnelles :
Localisation : France

Informations professionnelles :
Activité : Ingénieur développement logiciels

Informations forums :
Inscription : mars 2009
Messages : 333
Points : 584
Points : 584
Citation:
Envoyé par blazed Voir le message
Ca vous semble pourtant faisable ? Charger une instance de classe d'un objet Qt depuis une dll?
C'est faisable, mais ça me semble plus simple de passer par QPluginLoader.

Citation:
Envoyé par blazed Voir le message
Est ce qu'il faut que l'objet (enfin la class de l'objet) soit configurer pour l'import depuis une dll?
Sans ce qui précède, je pense qui faut rechercher une fonction dans la DLL qui te renvoie l'objet (LoadLibrary, GetProcAddress).
bretus est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 07/01/2013, 22h28   #7
blazed
Nouveau Membre du Club
 
Antoine
Développeur Web
Inscription : octobre 2008
Messages : 66
Détails du profil
Informations personnelles :
Nom : Antoine
Âge : 23
Localisation : France

Informations professionnelles :
Activité : Développeur Web
Secteur : High Tech - Éditeur de logiciels

Informations forums :
Inscription : octobre 2008
Messages : 66
Points : 31
Points : 31
J'ai creuse un peu, et il semble que ma dll qui retourne mon objet Qt a besoin des dll Qt. (Soite!) Mais il semblerait egalement que les dll ne trouve pas toutes les dependences nécessaires a leurs bon fonctionnement. J'ai verifier avec un logiciel de recherche de dependence pour les dll (je posterais le nom plus tard je ne m'en souviens plus) et il s'avere que mes dll ne charge pas correctement leurs dependences ce qui implique evidement l'arret sans erreur intelligible.

Je vais donc avoir recours a QPluginLoader pour la suite.

Merci a tous.
blazed est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Cette discussion est résolue.
Outils de la discussion

Navigation rapide


Fuseau horaire GMT +2. Il est actuellement 10h04.


 
 
 
 
Partenaires

Hébergement Web