Préprocesseur & gestion des fichiers cpp/Dll

C++

Le problème exposé dans ce sujet a été résolu.

Bonjour,

J'ai deux questions auquelle je souhaiterais de l'aide.En effet, je n'arrive pas a trouver de réponse. Je précise que mes class sont dans des DLLs

Première question, j'ai crée des structures de class pouvant être utiliser dans différent programme. Cependant, chaque programme a besoin "d'écrire" quelque ligne en plus pour "adapter" la class au programme. Est-il possible d'appeler ces deux trois fonctions suplémentaire depuis un autre fichier qui serait compliler en DLL et dans le programe. Et si oui comment faire?

Exemple:

1
2
3
4
5
6
//Class TMainMenu

void __fastcall TMainMenuP::FilesNewClick(TObject *Sender) // fonction de la class
{
    FilesNewClick(); //fonction qui est appeler dans le fichier commun entre le programme et le dll
}

Le but serait de crée un DLL ne necessitant aucune mise à jour particulière a chaque programme. Et un fichier contenant la mise a jour particulière qui lui, aurait un H qui ne change pas mais juste le CPP.

Ma deuxième question porte sur les DLLs je souhaiterais savoir si il était possible de crée un qqch comme ça

1
2
3
4
5
#if Compilation pour DLL
__declspec(dllexport) class TMainMenuP
#else //Compilation comme fichier de class clasique
class TMainMenuP
#endif

Ceci serait dans le but de pouvoir utiliser les class dans des DLLs ou "normalement" en fonction du besoin

Je remercie d'avance de l'aide que vous pourrez m'apporter ps: Je travail avec C++ builder RAD XE7

+0 -0

Bonjour…

Ne le prends pas mal, mais ta question est vraiment décousue et ça ne m'étonne pas quans tu nous dis, je cite, "je n'arrive pas a trouver de réponse.".

Est-il possible d'appeler ces deux trois fonctions suplémentaire depuis un autre fichier qui serait compliler en DLL et dans le programe

Tu peux reformuler cette question, s'il te plaît ? Car pour moi, ça ne veut rien dire.

À titre d'information, tu es tout à fait en droit, je pense, de surcharger (hériter) une classe dont tu as le fichier d'en-tête ; ce afin de fournir ta propre implémentation.

En ce qui concerne les DLL… Déjà, tu dois compiler ta bibliothèque pour deux cas de figure :

  • liaison de code dynamique à un programme : tu vas utiliser la DLL
  • liaison de code statique à un programme : tu ne vas pas utiliser la DLL.

Dans les deux cas, la compilation de ta bibliothèque va résulter en un fichier .lib que tu devras lier à ton programme pour utiliser statiquement/dynamiquement ladite bibliothèque de code qui renferme ta classe.

Tu dois pouvoir trouver les paramètres qui vont bien dans RAD XE7 (c'est pas du Embarcadero, ça ?). Je ne peux t'aider plus à ce sujet.

+0 -0

JE ne suis pas sûr de bien comprendre ta question. Mais:

Tu ne peux pas définir l'implémentation d'une classe à moitié dans une DLL et à moitié dans un programme. Techniquement la vtable ne peut pas être imcomplète lors de la compilation de la DLL.

Tu peux par contre tout à fait étendre une classe dont l'implémentation est définie dans la DLL. C'est régulièrement ce qu'on fait quand on utilise des bibliothèques genre QT, WXWidgets, etc.

Attention par contre avec les DLL en C++, il faut absolument que toutes les DLL C++ et le programme soient compilés avec le même compilateur, même version. Par exemple tu ne peux pas utiliser une DLL C++ qui a été compilée avec Visual Studio si tu utilises GCC comme compilateur pour ton programme, ou inversement; ça ne marche pas, à cause d'obscures stupidités non standard (name mangling entres autres). Ca marche pour les DLL C mais pas C++. Je dis ça parce que je me suis moi-même déjà cassé les dents avec par exemple la SFML (que j'ai dû recompiler moi-même) ou FMODEx (où là j'étais bésé parce que c'est une lib propriétaire)

+0 -0

je te remercie pour ta reponse Ge0. J'ai ma reponse pour la ma deuxième question. Mais je voudrais savoir si je pouvais rajouter une ligne dans ma DLL qui, si un autre DLL n'est pas présent (ma DLL contient des fonctions d'une autre DLL) elle n’exécute pas le code. Par exemple, ma DLL contient un

1
extern "C" void __declspec(dllimport) __stdcall ShowAPD(); //fonction appeller d'une autre DLL

Et je voudrais que si ma DLL n'est pas présente cette fonction ne soit pas appeler je suis pas sur d'être claire …

Pour la première je vais mettre un schéma et j'espere que ça seras plus claire. C'est vrai que la question est pas très clair moi aussi. Je sais comment je voudrais faire dans l'idée mais pas en pratique d'où la confisusion ^^"

Donc, l'applicaption principale appele la DLL (disons un fonction "Nouveau") Le problème est que la fonction "Nouveau" depend du programme (par exemple, chrome et paint n'ont pas la même definition de cette fonction)

Je voudrais donc crée un fichier ou qqch comme ça, que la DLL appelerais pour executer la fonction "Nouveau". Ce fichier aurait un .h que ne change pas (en effet les definitions sont les même à chaque fois) mais un .cpp qui change en fonction du programe.

Donc le programme principal appelle le DLLs qui appelle le "fichier neutre" qui exécute la fonction dans le programme principal.

En terme de compilation, le fichier neutre serait compiler dans la dll et dans le programme principal. (voir image, en vert qui appelle qui et en rouge, où le fichier neutre est compilé) Image utilisateur

+0 -0

Mais je voudrais savoir si je pouvais rajouter une ligne dans ma DLL qui, si un autre DLL n'est pas présent (ma DLL contient des fonctions d'une autre DLL) elle n’exécute pas le code. Par exemple, ma DLL contient un

1
extern "C" void __declspec(dllimport) __stdcall ShowAPD(); //fonction appeller d'une autre DLL

Et je voudrais que si ma DLL n'est pas présente cette fonction ne soit pas appeler je suis pas sur d'être claire …

En gros, tu as A.dll qui fait appel à une fonction de B.dll, et tu voudrais que si B.dll n'existe pas, alors A.dll continue normalement mais n'appelle tout simplement pas la fonction de B.dll ? En d'autres termes tu veux que B.dll soit optionel ?

Si c'est ça, alors tu ne peux pas faire comme ça, pas directement. IL faut charger la DLL à l'aide de LoadLibrary, puis récupérer un pointeur vers la fonction avec GetProcAddress. Car si tu inclus B.lib dans l'édition des liens, alors B.dll est obligatoire, et en cas d'absence ton programme ne peut pas du tout se lancer (le chargeur de windows t'indiquera qu'il manque la DLL)

+0 -0

Si c'est ça, alors tu ne peux pas faire comme ça, pas directement. IL faut charger la DLL à l'aide de LoadLibrary, puis récupérer un pointeur vers la fonction avec GetProcAddress. Car si tu inclus B.lib dans l'édition des liens, alors B.dll est obligatoire, et en cas d'absence ton programme ne peut pas du tout se lancer (le chargeur de windows t'indiquera qu'il manque la DLL)

J'ajoute : même dans ce cas, si tu n'as pas B.dll, il faut que tu gères le code de retour de LoadLibrary qui indiquerai que le chargement de la DLL n'a pu aboutir…

Hey !

Comme te l'ont dit QuentinC et Geo0, ce que tu cherches à faire est dans ta deuxième question est une bibliothèques à chargement explicite, tu peux jeter un coup d'œil ici : openclassrooms[…]/creer-des-bibliotheques-avec-code-blocks (note cela fonctionne sous windows et linux contrairement à ce qu'il est dit sur le cours d'OC).

Concernant ta première question, il est courant de compiler avec un flag/define comme "BUILD_DLL", voir :

1
2
3
# Commandes non essayées
g++ -DBUILD_DLL -c source.cpp source.o 
g++ -shared --output-def=libsource.def --out-implib=libsource.a --dll source.o -o libsource.dll -s -luser32

Ce qui ensuite permet ce genre d'implantation dans tes ".h" :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
/// File head.h
#ifdef BUILD_DLL
#define DLL_EXPORT __declspec(dllexport)
#else
#define DLL_EXPORT __declspec(dllimport)
#endif

int DLL_EXPORT Add(int a, int b);

class DLL_EXPORT MyClass
{
public:
        MyClass(unsigned int _myInt = 777);
        void func(void);
protected :
    unsigned int myInt;
}
1
2
3
4
5
/// File source.cpp
#include "head.h"
int Add(int a, int b) {  return (a + b); }
MyClass::MyClass(unsigned int _myInt) : myInt(_myInt) {    std::cout << "MyClass("<<myInt<<")"<<std::endl; }
void MyClass::func(void) { std::cout << "MyClass.func()"<<std::endl; }

Bien sur toutes tes classes et fonctions seront compilées uniquement dans le dll. Par conséquent le projet dll est composé des .h et .cpp et le projet utilisant le dll inclus seulement les .h du dll

+0 -0
Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte