[EDIT 3DArchi] Suite à cette discussion [/EDIT]
je n'ai pas compris... pourquoi ne pas exporter des classes ?
Version imprimable
[EDIT 3DArchi] Suite à cette discussion [/EDIT]
je n'ai pas compris... pourquoi ne pas exporter des classes ?
Tu importes tes classes comment en VB, par exemple ? Ou en Delphi, ou Fortran, ou tout autre langage qui n'est pas du C++ ?
Autre point "rigolo" : GCC et Visual n'utilisent pas les mêmes conventions pour le mangling => tu résouds ça comment ?
Une DLL "correcte", c'est uniquement des fonctions à l'export, toutes en convention d'appel stdcall, et bien sûr sans aucune décoration. Tu noteras d'ailleurs que c'est le cas de quasiment toutes les DLL système de Windows.
EDIT : Et en plus, dans un cas pareil, tu peux assurer au maximum un link JIT de la DLL en question, greffer un stub en lieu et place si elle est absente, bref avoir une gestion correcte de la présence/absence de la DLL et/ou des évolutions de version.
ah ok je vois
Et si tu veux toujours faire de l'orienté objet avec ça, il reste l'option de faire une DLL COM.
et en portable ?
Il n'y a pas de DLL en portable de toute façon. Je ne sais pas comment les SO marchent, peut-être ont-ils un mécanisme similaire à l'importation statique retardée...
Pas de portabilité, là on parle d'éléments natifs du système. Le mot "portable" n'existe même pas à ce stade ! ;)
Tu peux avoir des librairies d'encapsulation de ces mécanismes, permettant d'avoir "tout comme", mais cela demande à utiliser ces mécanismes justement. Par exemple, POCO fournit une API de type plugin qui permet effectivement d'avoir des équivalents de DLL JIT, mais ça t'oblige à développer ta DLL suivant cette architecture (donc, mort pour les DLL déjà existantes dont tu n'as pas les sources).
Pour les SO, il existe dlopen qui joue le même rôle que LoadLibrary sous Windows.
nan mais je connais mais je ne vois pas bien le rapport la
je ne comprends pas
Qt exporte bien des classes, ca marche. Et c'est pas la seule bibliotheque C++ du monde quand meme. du coup je ne comprend pas bien vos reflexions sur les DllCitation:
exporter des classes et non des fonctions depuis une dll, c'est s'exposer à de grandes déconvenues.
Essayez d'utiliser une autre C-Runtime que celle utilisée lors de la compilation de la lib Qt.
Essayez d'utiliser un autre compilateur que celui utilisé lors de la compilation de la lib Qt.
etc....
Bonjour,
Une petite lecture qui pourra te guider : Calling conventions for different C++ compilers and operating systems de Agner Fog. Copenhagen University College of Engineering.
mais la c'est plus du tout le probleme original, le probleme original etait qu'une DLL ne se charge pas sous Vista mais se charge sous Xp.
Le langage de la DLL n'a rien a voir avec ca.... a mon avis
Les DLL système de Vista ne sont pas totalement les mêmes que celles d'XP, pour commencer, et tu peux encore plus rigoler si tu changes de compilateur, de runtimes C/C++, etc.
Bref, ça a tout à voir au contraire : tu ne peux garantir une importation correcte d'une classe QUE si tu compiles avec la même chaîne de développement la DLL et le programme qui l'utilise... Et que tu prévois, bien sûr, la portabilité au niveau des différentes versions de ton OS (ne pas appeler des fonctions spécifiques Vista et espérer que ça marche sous XP, par exemple, ou utiliser des fonctions "deprecated" sur un vieil OS et s'étonner que ça plante sur un nouveau OS).
les DLL de l'OS ne sont pas ecrites en C++ je ne vois pas ce que le langage de la DLL vient faire la dedans
a mon avis les DLL de visual studio n'ont pas été redistribuées, il faudrait s'inquieter de savoir pourquoi la DLL ne se charge pas dans un premier temps. Il y a plus de chances que ce soit un probleme de redistribution du runtime C++ (qui ne fait pas partie de l'OS)
encore une fois, le fait que ce soit une DLL en C++ qui ne se charge pas, raf
La majorité des DLL de l'OS, pas "toutes".
Notamment, MSVCRT.DLL possède plusieurs exports C++ par exemple, tout comme COMSETUP.DLL, ADSLDPC.DLL, et sûrement pas mal d'autres (mais je n'ai cherché qu'une minute aussi).
Essaie de linker les éléments C++ de ces DLL avec, par exemple, un programme compilé avec GCC et tu comprendras mieux.
Cela reste une très mauvaise pratique en soi d'exporter directement tes classes (ou des variables globales) depuis tes DLL. OK, ça modularise ton projet, mais ça ne rend en aucune façon tes DLL réellement réutilisables comme elles devraient l'être. Tu te coupes de la portabilité inter-langages, voire inter-compilateurs.
devoir coder en C pour la portabilité inter langage ca brise un peu le côté inter langage quand meme.
je veux avoir la preuve que cette DLL utilise des appels systemes de l'OS non supportés. comme cité plus haut, je parie a 99% que ca ne depend pas de l'OS mais qu'il manque une dépendance (le runtime Visual C++ 2005 a 98%)
MSVCRT.DLL est la DLL du runtime C++ de visual studio. Forcément, oui, elle contient un certain nombre d'appels au C++
Ce n'est pas "devoir coder en C", mais "avoir une interface C". Et encore, "avoir une interface VB" serait plus juste.
On peut tout-à-fait exposer des fonctions développées en C++, du moment qu'elles peuvent être appelées depuis le C (en clair, pas de types C++ en paramètre, déclaration extern "C"), et qu'elles utilisent la convention d'appel __stdcall (pour être compatible avec les autres langages). Ensuite, il est préférable que les noms ne soient pas décorés, mais s'ils ont une décoration C, ça n'est pas trop grave (.Net et VB ont les bonnes options pour contourner cela, et je pense que beaucoup d'autres langages aussi).
On peut aussi, si on le fait bien, exposer des fonctions retournant des pointeurs vers des classes C++ abstraites. C'est le cas pour les DLLs COM implémentées en C++...
54 symbols C++ exporté sur 829, tous en lien direct ou indirect avec le RTTI.
Donc c'est fait par NECESSITE, pas pour simplification ou "utilisabilité".
À ma connaissance, on ne peux pas changer le nom d'exportation d'une méthode de classe C++. Alors que sa convention d'appel, on peut la forcer.
Pour les fonctions isolées par contre, ce doit être l'inverse. En VB, on doit pouvoir contourner tout problème de nommage, mais la convention d'appel doit être __stdcall.
MSVCR90 a 65 symboles C++ sur 1451, tous liés à des trucs spécifiques au compilateur et qui ne peuvent être que là: RTTI, gestionnaires d'erreurs C++, etc.
Par contre, MSCVP90 contient la STL de Visual, et exporte 3110 symboles C++.
Dans tous les cas, ces deux DLLs sont spécifiques à Visual, et même à cette version de Visual, et n'ont jamais été censées être portables.
Interface "Pascal", aussi, du moins "historiquement"...
Pour une bonne DLL portable, il faut les éléments suivants :
- Convention d'appel stdcall.
- Aucune décoration de nom : cela peut changer, ou devenir très difficile à automatiser pour des wrappers automatiques type SWIG.
- Types natifs exclusivement, de préférence ceux définis dans "Windows.h".
- Fuir les chaînes de caractère, ou alors les fournir allouées par la DLL et sous forme de pointeur.
Avec ça, OU une interface COM, t'es tranquille. Sans ça, t'es potentiellement dans la mouise.
c'est tellement restrictif que c'est presque ingérable. Principalement, les classes "helper", les template, le RAII, tout cela doit disparaitre dans le code client
Désolé si je parais "sec", mais si tu trouves ça restrictif, c'est qu'il te reste beaucoup de choses à apprendre dans le domaine de la conception...
Si c'est trop restrictif, c'est que tu as mal découpé tes modules, et/ou que tu n'as pas su les décomposer en problèmes élémentaires. Une DLL, c'est fait pour du code compilé, partagé et réutilisable : ça n'offre AUCUN intérêt si ce n'est pas le cas !!
mon code est dans une DLL, il dépend malheureusement de la gestion des resources avec du RAII, j'utilise des smart pointers et des weak pointers, des scoped mutex lock, etc etc
et ca fait (mal)heureusement partie de mon code; on utilise pas un mutex, un utilise un scope de mutex. parce que je veux pas que le premier scribouilleur de C++ vienne locker un mutex et oublie de le délocker avant de faire son return.
et je considère ca comme la meilleure API du monde, loin devant des fonctions à la convention d'appel ultra portable qui vont être source de déconvenues partout.
C'est bien ce que je disais...
Allez, je vais t'aiguiller sur les bonnes solutions :
- Comprendre la notion de "handle".
- Définir le besoin et publier sa résolution, et non pas la tripaille de la résolution.
- Savoir abstraire et encapsuler.
Bref, au lieu de dire "je ne peux pas publier ma méthode de template Z qui sélectionne un mutex libre dans mon pool global instancié via spécialisation", as-tu par exemple envisagé de faire une fonction (portable) "handle GetMutex()", avec son corollaire "bool TakeMutex(handle)", toutes deux parfaitement exportables de façon portable ? Et c'est ça que tu appelles "être source de déconvenues" ? ;)
Cela demande à gérer des tables de handle (y compris avec des std::map si ça te chante !!!), à considérer la fonction globale plutôt que le détail d'implémentation, à savoir différencier le code devant être public du code devant être privé, à utiliser des fonctions comme les TLS, etc.
Je n'ai pas dit que c'était trivial à faire, au contraire même. Mais c'est la différence entre faire quelque chose de réellement portable, réutilisable partout, et faire quelque chose qui reste finalement très tentaculaire malgré sa séparation en multiples .EXE et .DLL : car que t'apporte ta DLL, exactement ?
Est-elle déjà au moins utilisée par plusieurs applications en même temps, sur la même machine ? Est-elle réutilisable dans d'autres projets, quel que soit le langage utilisé pour le développement ? A-t'elle la moindre interopérabilité ? Est-elle réellement portable, y compris sur Linux ?
Faire une DLL, c'est facile. Faire une BONNE DLL, c'est très difficile.
Il y a d'autres problèmes. Par exemple, si dans une interface, on passe une classe std::string, sachant que cette classe peut-être implémentée complètement différemment entre deux compilateurs C++ (et je ne parle pas de la compatibilité avec d'autres langages). Si on veut une DLL utilisable par d'autres langages, il faut se restreindre à ce qui est commun. Avec les DLL classiques, c'est très limité. C'était je pense un des buts du CLR de Microsoft, avoir un socle commun où des langages différents pourraient communiquer avec un vocabulaire et une grammaire plus riches que le C, mais malheureusement, c'est un langage que le C++ ne peut pas vraiment parler. C'était aussi un des buts de COM, mais je pense que le problème a été pris du mauvais côté, et qu'on devait passer par des traducteurs fort coûteux pour vraiment communiquer.
Je te trouves trop extrémiste ! Une DLL, ça peut aussi être utilisé simplement pour gérer des plug-ins dans un monde où de toute façon 95% (chiffre pifométrique) du marché des compilateurs sous windows est pris par 1 compilateur, que pour les 2/3 options de compilation qui comptent dans la pratique, on peut assez facilement se mettre d'accord entre fournisseur du module principal et fournisseur du plug-in, et que développer une DLL exposant son interface en C++ peut coûter bien moins cher (temps de dev et temps d'exécution) que de déveloper des wrappers pour passer en C dans chaque côté de la frontière.Citation:
Envoyé par Mac LAK
Moi, j'appelle ça effectivement se créer des soucis si on est dans un contexte mono-compilateur/mono langage. Car ça impose d'avoir un wrapper "c" du code de la bibliothèque (tes fonctions GetMutex et TakeMutex), et côté code client, un autre wrapper pour re-rendre ces fonctions utilisables en C++ (réintroduire le RAII, principalement). Ces deux wrappers ont un coût d'écriture, de maintenance et d'exécution, et il y a des contextes de travail où ils n'apportent aucun avantage.
oui, car
est possible, alors queCode:
1
2
3 TakeMutex(mutex); //ReleaseMutex(handle); oops j'ai oublié de le liberer return;
est du code andouille-proof, personne ne peut le casser comme celui plus haut.Code:
1
2 Mutex::Lock lock(mutex); return;
tu questionnes des trucs sans même savoir, je trouve que la tu me prends un peu de haut. Je connais quelques trucs en portabilité quand même.Citation:
Je n'ai pas dit que c'était trivial à faire, au contraire même. Mais c'est la différence entre faire quelque chose de réellement portable, réutilisable partout, et faire quelque chose qui reste finalement très tentaculaire malgré sa séparation en multiples .EXE et .DLL : car que t'apporte ta DLL, exactement ?
Est-elle déjà au moins utilisée par plusieurs applications en même temps, sur la même machine ? Est-elle réutilisable dans d'autres projets, quel que soit le langage utilisé pour le développement ? A-t'elle la moindre interopérabilité ? Est-elle réellement portable, y compris sur Linux ?
Non, pas extrémiste : un plug-in, c'est quelque chose de très différent d'une DLL. Certes pas dans sa "forme" macroscopique, qui reste une librairie dynamique, mais dans son BUT initial.
Un plug-in est, par nature, bridé et indissociable d'une application donnée, et il n'y a donc rien d'étonnant à devoir utiliser le compilateur de l'application hôte pour réaliser ledit plug-in. De plus, un plug-in est normalement capable d'être ajouté et retiré "à chaud".
Une DLL est, par nature elle aussi, destinée à assurer un service quelconque au niveau système, et donc se doit d'être utilisable par le maximum possible de langages / compilateurs. Comme le plug-in, on doit normalement être capable de la monter / démonter à chaud.
Pour le RAII, tu as (entre autres) les TLS qui servent à ça, tout comme les events gérés par DllMain : c'est souvent même nettement plus puissant qu'un RAII "classique".
Pour le reste, si tu es en contexte mono-compilateur et mono-langage (cas rare, t'as souvent des modules C quand même), l'intérêt d'une DLL C++ exportant des classes est très limité : pas de liens JIT, ou alors sous conditions (pas de déchargement notamment), peu ou pas de réutilisabilité... Quel est dans ce cas l'intérêt d'une DLL, à part de séparer un peu le code ? Autant faire une librairie statique...
Event "thread-detach" de DllMain, par exemple, si t'es dans un corps de thread... Au pire, tu le fais au déchargement de la DLL (process-detach) : les handles ne sont pas obtenus par miracles, ils sont maintenus en mémoire et peuvent donc être libérés à volonté.
On peut même faire ça de façon portable en faisant de la classe gérant les handles un singleton, bien entendu privé à la DLL, ce qui permet de pallier l'absence de DllMain sur les systèmes Unix. De même, tu peux avoir des fonctions "Register()" / "Unregister()" au niveau thread et/ou processus pour gérer les contextes d'exécution.
De plus, si tu es dans un contexte de template, ton "Mutex::Lock" est un template pur (=> pas de code, juste un .H), et tu colles tes appels (propres) à la DLL dans le code du constructeur/destructeur. Bref, toujours pas besoin d'exporter des classes depuis la DLL...
Dernier point : oublier de relâcher un mutex est une erreur triviale à trouver, donc inutile de blinder à tout bout de champ à ce sujet. On s'adresse à la base à des développeurs quand même, et non pas au lambda moyen n'ayant jamais fait une ligne de code de sa vie... Simplifier la vie du développeur, OK, mais si tu commences à présupposer qu'il a été amputé du cerveau, t'as du pain sur la planche.
Ce qui ne réponds pas aux questions que je t'ai posées précédemment...
Tes arguments en faveur d'un export de classe, je les ai entendus cent fois dans ma carrière, toujours présentés comme des problèmes soi-disant insolubles sans exporter une classe, et limitant plus que fortement la réutilisabilité de la DLL... Notamment vers des systèmes orientés métier ne possédant qu'un compilateur C (et non pas C++), d'ailleurs.
Je peux pourtant te garantir que des solutions propres et portables, ça existe presque systématiquement, les exceptions étant franchement ultra rares... Et ce n'était jamais le cas des soi-disant "impossibilités" que l'on me présentait.
Ne jamais prendre les développeurs pour des cons.
Le code andouille-proofs, tout développeur digne de ce nom est capable de le faire autours d'une librairie C. En plus il peut facilement être fourni dans le fichier de header que l'on fournit avec la dll et le fichier lib.
On peut aussi fournir ces wrappers pour d'autres langages et les développeurs peuvent les modifier en fonction de leur besoin réels et non supposés.
Faire une bonne dll, c'est surtout en faire une simple, pas une simpliste.
Franchement, je suis avec JolyLoic pour le RAII, à cela près que j'ai tendance à me contenter de classes inline wrappant des fonctions à interface C.
Edit: Ou de pointeurs intelligents vers des classes COM...
je préfère toujours assumer que si on en laisse la possibilité, quelque chose va aller de travers. Forcément, mon code la il est évidemment buggé, mais ca peut etre au sein d'une plus grosse fonction, dans une boucle; avec plusieurs points de retour de la fonction; et si on en ajoute un sans faire attention : kaboom. c'est aussi facile a debugger avec un mutex, mais si c'était un leak mémoire, ca passeait inapercu.
je passe ma vie a corriger des bugs (c'est mon boulot) et j'ai noté que les erreurs étaient rarement individuelles, que modifier du code a un endroit pouvait casser un autre endroit seulement vaguement similaire; s'aider du compilateur pour éviter ces déconvenues est souvent une bonne idée.
Sauf qu'une fuite mémoire est rarement "simple" à gérer : c'est plus que rarement nécessaire au sein d'une seule et même fonction (=le cas où, justement, un pointeur intelligent aide bien), et inter-fonctions, c'est à dire avec des allocations un minimum persistantes, tu n'es pas dispensé d'un appel explicite à delete pour assurer le boulot correctement.
Pour ce genre de choses, j'aime bien utiliser le TLS pour indexer des objets C++ "planqués", quitte à publier un template wrapper (100% inline) dans les entêtes pour aider à, par exemple, initialiser / détruire correctement les données au sein d'un thread (dans sa fonction principale) et/ou processus (dans le main).
Bien entendu : c'est pour ça aussi qu'exporter des fonctions "simples" d'une DLL, éventuellement avec des choses complexes de façon interne (classes singleton, mémoire partagée, TLS au taquet, etc.) pour aider à la libération est une bonne chose.
Car tant que tu maintiens l'interface identique, ou au moins rétrocompatible, tu t'assures que tu ne casses pas de code par effet de bord.
Le cas typique, c'est la mise en obsolescence d'une fonction (peu ou pas assez sécurisée, par exemple) : en interface DLL C, aucun souci, tu peux rajouter la fonction sans enlever l'ancienne, ni exiger de recompilation des anciens modules. Ils fonctionneront à l'identique, et les nouveaux modules (ou ceux corrigés) profiteront de la nouvelle fonction plus fiable.
Avec une classe C++ exportée, comme la VMT change, tu t'obliges déjà à tout recompiler sans exception, anciens comme nouveaux modules : soit tu as rajouté la fonction, et l'ancienne VMT n'est plus applicable (=> recompilation), soit tu remplaces l'ancienne fonction (=> effets de bords et/ou régressions), soit tu dérives une nouvelle classe (=> modifications plus ou moins lourdes du source)...
L'intérêt de la DLL, dans ce cas, est plus que limité !
pourquoi appeler delete a la paluche alors que quelqu'un d'autre (sous entendu le compilateur) peut le faire pour toi ?
Mais comme je dis, si tu as mis tout le code dans le C, tu peux très bien faire ça en inline: Juste un constructeur et un destructeur.
C'est la même chose avec COM: Un petit CComPtr<>, _com_ptr_t<> ou boost::intrusive_ptr<> suffit à assurer la libération automatique sans que tu aies à donner une interface C++ à ta DLL!
Tu fais comment quand ton objet doit "vivre" un certain temps, passer les frontières des fonctions et/ou des threads ?
A un moment donné, forcément, il n'existe plus qu'en tant que pointeur quelque part, passé aux fonctions : il faut bien décider à quel moment on n'en a plus besoin, et le détruire explicitement. Ça, c'est pour le cas d'un objet transférable.
Dans le cas d'un objet limité à une portée de fonction/bloc, comme le souligne Médinoc et comme je te l'ai dit, un wrapper inline (= non exporté par ta DLL) résoud ton problème, SANS empêcher la DLL d'être portable/réutilisable...
Vous faites ce que vous voulez; on tourne en rond la, alors je mets le sujet en résolu, libre a vous de faire vos DLL avec l'interface que vous souhaitez. Je ne suis pas la pour vous convaincre, j'ai enoncé mes points plus haut je ne me sens pas de les répéter.
OK, mais pourquoi éluder les questions que l'on te pose ?
Je te demande comment étaient utilisées tes DLL, pas de réponse. Je te demande comment tu fais pour des objets devant vivre en dehors d'un bloc d'instructions connu à l'avance, tu éludes aussi. Tu fais comme tu veux, mais bon : ce n'est pas en évitant de répondre aux questions directes que tu feras valoir ton point de vue...
ce ne sont pas des questions simples
comment j'utilise ma DLL : je n'ai pas de "DLL", ou plutot mon executable sur cetraines plate-formes est une DLL. Je fais un jeu, avec un éditeur, qui utilisent cetraines bibliothèques, et qui fonctionne ou devra fonctionner sous plusieurs plate formes
le moteur en lui même est un ensemble de lib statiques (reparties en modules). Ces libs sont ensuite liées avec le jeu, et le jeu exportent les symboles, y compris des modules plus haut; donc en gros, j'ai une bibliotheque (statique) Engine, laquelle est liée avec Jeu. Jeu exporte les symboles venant a la fois de Jeu et de Engine.
Ensuite, Engine est aussi lié avec Editeur pour faire un nouvel executable; Editeur est également un jeu en quelque sorte (ce qui me permet d'éditer l'éditeur lui même, c'est rigolo) et ils sont censé communiquer par le réseau (malheureusement je n'ai pas encore commencé cette partie).
l'API est exportée de deux facons; il y a d'abord l'export de l'API C++ pour ecrire des plugins, puis il y a l'export des classes du jeu qui permet de fournir automatiquement un certains nombre de composants (plus haut niveau) a des langage au runtime dynamique (en ce moment, Lua, plus tard, squirrel et python, peut-être C#)
il est possible de changer Engine en DLL sans trop de probleme; Engine est un ensemble de modules, il est possible de compiler chaque module en DLL.
Sur certaines plates-formes (consoles) l'éditeur n'est pas lié et il n'y a pas de support pour les plugins; dans ce cas, rien n'est exporté, la table d'export est vide et le jeu est un executable statique. Dans d'autres cas, il vaudrait mieux faire plusieurs DLL ou au moins engine.dll pour ne pas dupliquer le code sur le disque. Tout ca se change simplement a partir du Makefile. Voila comment j'utilise une DLL.
Tu demandais si c'etait portable, oui, ca tourne en ce moment sous Linux et Windows, Solaris testé un peu (OpenSolaris et SOlaris 10) (mais il manque des bouts), FreeBSD vaguement essayé, MacOS vaguement aussi. Disons que je n'ai pas ecrit tout le code specifique encore. J'essayerai de trouver le temps pour la Wii et la PSP un jour, mais pour l'instant je n'ai pas encore essayé. j'ai juste laissé la place. Ca compile sous Windows avec Intel C++, Visual C++ ou GCC; sous linux avec GCC ou SunCC ou OpenCC; sous les autres plate-formes, GCC ou SunCC (encore que j'ai cassé SunCC recemment)
Tu demandais si on pouvait utiliser avec d'autres langages, oui et non. Un temps on pouvait utiliser avec C#, je l'ai desactivé car c'était assez lourd a recompiler et je ne l'utilisait pas, mais je le remettrai peut-etre. On peut utiliser avec Lua, on pourrait mettre d'autres langages. je ne les ai pas mis par flemme; tant que je ne les utilise pas, je ne les mets pas.
En résumé, plate-formes : sans doute plus que tu l'imaginais, probablement quelques unes que tu n'as jamais vu. Meme différents CPU.
langages : quelques uns, en tous cas il y a la place. il suffit d'ecrire un plug in pour publier pour un langage.
De plus, il y a une séparation entre le code (C++), le code moteur (publié aux scripts), les données. Il y a un langage de description de données que l'éditeur et le jeu utilisent.
Pour ta deuxieme question sur les pointeurs, je dois avouer que cette discussion m'a poussé a rechercher a me débarasser encore des pointeurs nus. Dans mon projet, les pointeurs nus sont des alias de "weak" car je n'ai pas encore ecrit la classe weak pointer.
mais dans ce projet, et selon mon API, delete est un mot-clé quasiment interdit; tout objet créé (y compris via scripts) est encapsulé soit dans un refptr soit dans un weakptr. les fonctions exportées ne créent pas des pointeurs nus, elels créent des refptr. dans mon esprit toujours un weakptr n'est qu'un wrapper de refptr, et si il reste des weakptr lorsqu'un refptr est detruit alors une assertion est lancée. Enfin, personne n'est censé appeler delete; les refptr sont les seuls garants de la durée de vie des objets.
Il y a un scopedptr egalement mais je m'en sers peu; scopedptr est inutile en général car si un objet a la durée de vie d'un scope, je le mets sur la pile, je n'appelle pas new.
Comme j'ai énoncé plus haut aussi, on ne lock pas un mutex (ou alors c'est du vieux code que je n'ai pas encore porté); on crée un scoped_lock
et j'essaye de me débarasser de new pour utiliser un outil de création qui crée un scoepd ptr au lieu d'un pointeur nu. Bref, le pointeur nu est plutot banni quoi.
La seule chose qui m'ennuie, c'est de ne pas pouvoir stocker de scopedptr dans des containers, ce qui m'oblige a avoir des pointeurs nus, j'essaye également d'adresser ce problème.
voila pour la réponse a tes questions.
Je n'ai jamais dit qu'elles étaient simples... ;)
Typiquement, dans ton cas, la DLL n'apporte aucune "solution" à part celle de réduire la place sur le disque. Donc, "aucun intérêt" en soi d'avoir mis ton moteur en DLL ou pas, à l'exception notable de l'économie de place disque.
J'ai parlé du cas des plugins précédemment, qui est un cas très particulier justement (encore que, c'est facile de faire des plug-ins portables s'ils ne font que des calculs...).
Côté wrapping vers des langages interprétés, tu risques vite d'avoir quelques désillusions avec des classes C++... Des outils comme SWIG pourront toutefois te simplifier un peu la vie.
Mais la portabilité inter-langages, elle, n'existe du coup pas...
Pour le reste, tu as utilisé une couche d'abstraction type ACE, ou implémentation "manuelle" ? Cela simplifie beaucoup cette phase...
La question serait plutôt : si tu compiles ton moteur avec GCC, peux-tu l'utiliser dans un éditeur compilé avec VS ?
Oui, mais ce sont des solutions de wrapping, et non pas réellement d'utilisation depuis d'autres langages. Typiquement, je ne pense pas que tu arrives à connecter dessus un programme en VB, en Delphi, ou même simplement en C++ mais compilé avec un autre compilateur (ex : GCC si tu l'as compilé avec VS ou ICC).
Heu... Méfies-toi, j'ai touché un sacré paquet d'OS et de CPU différents... ;)
Et ce plug-in sera compilé suivant quelleS interfaceS ? Interface interne (côté moteur), et interface externe (côté langage), donc.
OK, et tu les détruits quand, ces pointeurs de référence ? Sachant que pour moi, appeler explicitement le destructeur, une méthode "Free()" ou un delete, c'est du pareil au même : cela reste une destruction explicite.
Mais c'est ce que Médinoc et moi t'expliquions : cela n'est absolument pas incompatible avec une interface C sur ta DLL.
je n'appelle pas delete a la paluche, jamais; c'est le refptr qui l'appelle. il n'y a pas d'appel au destructeur explicite, ni d'appel a delete; c'est le but meme du refptr, il va "implicitement" appeler le destructeur
je ne voulais pas dire "plus de plate formes que tu en aies vu de ta vie" mais juste "plus de plate forme que tu croyais que je connaissais". tu as eu un ton assez condescendant plus haut.
pour le reste, je n'ai pas compris pourquoi tu disais que c'etait inutile d'avoir une DLL. c'est, en quelque sorte, jamais utile; on pourrait tout faire en statique ?