Envoyé par
koala01
Salut,
Cependant, je me rend compte que ce qui risque de poser problème pour beaucoup d'entre vous est... que tous le mods créés pour minecraft risquent d'être à refaire.
J'ai simplement envie de poser la question "Ah bon, et pourquoi donc
"
Car, à moins qu'il ne s'agisse réellement de remplacer un fichier .class par un autre (dans lequel on a modifié le code d'origine, oserais-je dire), il y a énormément de projets "multi langages" qui utilisent une base de C++ dans certains coins, une base de java dans d'autres et, qui sait, pourquoi pas un peu de C#, de python ou de n'importe quel autre langage encore ailleurs.
A vrai dire, je me demande même s'il y a vraiment un seul langage qui soit tout à fait incompatible avec n'importe quel autre (mis à par le C peut-être
).
Pas expert en dev non plus donc.
Pour info, quand on fait des bibliothèques partagées, le C++ est incompatible avec lui-même, potentiellement d'une version d'un compilateur à une autre version du même compilateur, sans parler entre divers compilateurs. Je parle bien des binaires générés, hein, par du code source.
Les langages ne sont généralement compatibles qu'avec le C, et c'est de par cette compatibilité C (qui est quand même limitée, qui impose en général de se taper du code spécifique d'import de fonctions, pas toujours si simple. En C# j'avais essayé, mais essayer de comprendre ces histoires de pointeurs sécurisés ou non, et le fait d'appeler tel ou tel truc sécurisé ou non d'une portion de code qui ne l'est pas était une galère sans nom. En Java il me semble que c'est moins lourd.) qu'ils sont compatibles les uns avec les autres.
Quelques éclaircissements au sujet de l'incompatibilité du C++ avec lui-même, il faut savoir que l'ABI n'est pas imposée par le standard, pour que les éditeurs de compilo/lib standard puissent optimiser le comportement dans la direction qui leur sied. Et ensuite, garder une API stable d'une version à l'autre d'un système n'est pas aussi évident pour un langage natif que pour un langage interprété/semi-interprété (ou qui tourne sur une VM, comme vous préférez). Ajouter à ça les différences entre les systèmes, que ce soit l'OS (win/linux/*BSD) ou le matos (32/64bits, x86/arm, big/small/whatever endian,...).
Quelques exemples:
* Le C (et donc le C++) fournit des types par défaut dont la taille varie selon l'architecture. En 16 bits, un int faisait 16 bits, en 32 bits il en fait 32. En 64 bits, ça dépend de l'OS sous-jacent. A savoir que, le C++ fournit en standard des types dont la taille minimum et/ou maximum depuis plus longtemps que C++ (uint32_t, uintleast32_t, ce genre de trucs). A l'origine, ils ne fournissaient que ces types à taille variable. J'ai découvert ce problème en BTS, parce que je savais programmer avant, et que j'utilisais de vieux compilos 16bits, et j'ai très rapidement cessé d'utiliser les types natifs, sauf les char (qui eux, sont stables à priori... pas garantit, mais ça doit au moins être compatible ASCII, donc minimum 7 bits, et je doute qu'il reste beaucoup de proco qui utilisent des bytes de 7 bits...). D'ailleurs, pourquoi la SDL offre-t-elle des types non natifs (INT32 p.e.) (on peut aussi se demander pourquoi elle n'utilise pas les types standards, mais la réponse est simple: Visual Studio, au moins jusqu'au 2005 inclus, ne fournissait pas stdint.h, pourtant standard C99 (mais C++11 seulement, oui ce sont des langages différents)).
* L'implémentation des vtables, le truc qui permets le support de la RTTI (qui est d'ailleurs un mécanisme coûteux), est laissée à la discrétion du compilateur. Si la vtable est encodée en mémoire au début de la classe, ou après les données de la classe, ou dans un segment différent selon le compilateur, les ABI de la classe pètent, et un binaire C++ ne pourra pas être exploité d'un système à l'autre.
* les exceptions, dont l'implémentation n'est pas spécifiée par le standard, encore une fois. Par exemple, que spécifie le standard quand une exception n'est jamais rattrapée? Et si elle est lancée d'un binaire différent (appel d'une "DLL" par une autre ou par un exécutable, par exemple et pour faire simple) sans être rattrapée dans ce binaire (mais l'est dans le binaire appelant)?
* l'alignement mémoire, qui est un problème matériel mais qui ne concerne pas les langages non natifs (sauf ceux qui font joujou avec le réseau, j'imagine?).
Bref, écrire du code natif et portable n'est pas aussi trivial qu'on peut le croire. Surtout si en plus on veut un truc un peu performant.
Le faire en C++ relève de l'impossible, sauf si l'on accepte de ne pas utiliser un certain nombre de fonctionnalités C++. Je m'étais penché à une époque sur la création d'un système de plug-in, où l'API comme l'ABI doivent être rétrocompatibles au maximum d'une version à l'autre (il y à de bons articles dessus sur drdobbs pour les curieux) et en gros, la méthode classique (la plus simple aussi), c'est de ne fournir que des structures et des fonctions qui prennent ces structures en paramètre qui les génèrent et les nettoient, des "classes dépliées" donc.
Sauf que... pour qu'une telle bibliothèque soit exploitable à fond en C++, il faut fournir les détails d'implémentation de la structure, sinon il sera impossible de l'utiliser dans des templates, tels que std::unique_ptr. Ou, au moins, donner au compilateur un moyen de connaître la taille de cette structure (attention à l'alignement, ici).
Je pense que le C est probablement le langage qui à la compatibilité maximale avec les autres langages, grâce à son manque de complexité. Et pourtant, ça reste loin d'être simple, de faire du code portable et efficace.
Dés lors, j'ai envie de dire que, pour que les mods fonctonnent, il "suffit" de deux choses :
- que microsft puisse mettre un système de plugins cohérent au point pour son code C++ et
- qu'ils fassent en sorte que ces plugins puissent être écrits dans différents langages
Entre des projets "à plugins multiples" comme peut l'être visual studio (et d'autres projets de chez eux) et l'expérience tirée de .NET en ce qui concerne la compatibilité, je ne doute pas vraiment qu'ils aient les connaissances et la capacité à résoudre ces deux points
J'aurai surtout cité le fait qu'ils maintiennent un OS depuis +20 ans, et le fait qu'ils arrivent encore à exécuter des binaires datant de w95, quand le binaire en question n'est pas trop mal écrit. Pas sûr que ce serait faisable sous linux (et je suis un linuxien développeur C++, je suis parti pris, mais de l'autre côté
).
En tout cas, la réécriture complète d'une application est vraiment l'avant dernier recours en général. Le dernier étant de changer le langage au passage, et je ne le ferai que si il ne m'est pa possible de trouver les outils nécessaires pour travailler dans l'ancien langage sur mon environnement (typiquement, du code delphi exploitant des routines win32 quand on ne dispose que d'une Debian...).
Le code originel doit vraiment être dégueu, donc, parce que le plus simple aurait été de balancer le code dans des bibliothèques tierces, potentiellement écrites dans un autre langage. Certains arrivent même à faire ça à partir d'un binaire après tout (bon, forcément, quand on à pas le source originel... je pense notamment à keeperfx). Ou alors ça doit vraiment en valoir la chandelle.
6 |
0 |