Connexion
Vous n'avez pas encore de compte personnel ? Vous devriez en créer un. Une fois enregistré vous aurez certains avantages, comme pouvoir modifier l'aspect du site, ou poster des commentaires signés...
Support
Activité du Site

Pages vues depuis 06/01/2019 : 6 782 941

  • Nb. de membres 363
  • Nb. d'articles 2 684
  • Nb. de forums 24
  • Nb. de sujets 13
  • Nb. de critiques 0

Top 10  Statistiques

Index du forum »»  Développement »» Les bibliothèques en mode 'baserel' et leurs problèmes...

Les bibliothèques en mode 'baserel' et leurs problèmes...#334

2Contributeur(s)
Yomguirmais96
2 Modérateur(s)
PapiosaurBeWorld
Yomgui Yomguiicon_post
J'ai rajouté une section FAQ dans la page Python de mon wiki.
J'y explique justement pourquoi la python.library est compilée dans ce mode particulier et pourquoi cela cause bien des pb avec python en particulier.

rmais96 rmais96icon_post
Intéressant ces explications.

J'ai esayé de me frotter à Pyrex qui est sensé permettre :
- De créer des applications natives (i.e. compilée avec Gcc) écrites en Python,
- D'encapsuler du code C/C++ pour pouvoir l'appeler depuis du code en Python.
Malheureusement, même si la compilation passe, le résultat n'est pas fonctionnel.
L'utilisation du résultat conduit à des exceptions "Illegale data access" y compris
dans les autres applications. Je n'ai pas compilé en mode "baserel", c'est peut-être
la cause des problèmes.
Yomgui Yomguiicon_post
@rmais:

il faut que je fasse une page compléte juste pour expliquer les problèmes causés entre le baserel et Python.
Grosso merdo, Python exporte de façon directe plusieurs choses:

- Les fonctions de la lib elle-même (tous les Pyxx ou _Pyxxx).
- Les variables: tous les types et quelques variables et constantes.

Comme je l'explique dans ma FAQ, la compilations en baserel va permettre d'avoir ces variables définis par tâches et non pas globalement. Avec le script cv!!!include!!!s.pl dans le SDK de MOS on va aussi générer 2 choses:
- les inlines ppc
- les 'trampolines' pour la libpythonX.Y.a

Les deux permettent de sauver/restorer r13 dans la pile et forcer r13 avec le bloc de données sauvé quelque part dans la base (PythonBase) et ce avant l'appel effectif au code souhaité.
Ainsi le code est exécuté avec les bonnes données.
Evidement r13 est sauvé/restoré lors d'un switch de contexte du système.

Mais tout serait parfait dans le meilleurs des mondes si justement tout code utilisant la lib python n'appelerait QUE les fonctions de la lib.... sauf que le code python exporte des types!

Et un 'type' python c'est une structure contenant plein de fonctions... venant de partout (lib, module, extern) et donc pas de protection particulières vis-Ã-vis de r13 et pouvant être appelées de partout:
- si appel depuis la lib python: ok, r13 est déjà correct à ce moment là avec nos trampolines.
- si appel depuis un module .pym extern:
si ils sont compilés avec le module distutil que j'ai adapté pour mon port, alors pas de pb, car eux, bien qu'ils ne soient pas en baserel, j'utilise une option de gcc qui permet de ne pas générer d'instructions modifiant r13. Et là on retombe dans le cas de base.

Et là les deux cas critiques non protégés (r13 n'est pas forcé):
- la fonction exportée par le type est appelé par un code quelconque (comme le fait blender en quelques endroits, par exemple): évidement ce code est compilé avec ces propres options et manière, on ne peut donc rien garantir sur r13!
- les modules peuvent aussi exporter des fonctions comme des API (cf http://docs.python.org/3.1/extending/extending.html#providing-a-c-api-for-an-extension-module ) utilisable par d'autres modules (là ça va car module python = r13 protégé), mais aussi par un code quelconque!! Et là c'est comme le cas d'avant!

Pour résumer, pour qu'un code quelconque, utilisant Python, fonctionne il faut:
1) aucun appel direct aux fonctions exportées dans les structure des types.
2) ne pas utiliser les API exportées, sauf si on protége r13 soit même!

Compiler ton code en baserel ne changera pas grand chose: il protégera la valeur de r13 avant tout appel externe certe, mais il protége sa valeur... et pas celle devant être utilisée pour l'appel!
Il faut absolument respecter mes 2 points sinon rien...

Il existe par contre 1 excéption seulement à ces régles: si ces appels (dans 1) ou 2)) ce font dans une fonction utilisée comme
méthode d'un type: puisque cette méthode est supposée être correctement appelée, r13 est correcte à l'appel! Mais cela implique que cette méthode ne soit en aucun cas en baserel! Il faut pas commencer à mélanger les bases entre elles.
Voilà d'ailleurs pourquoi les modules .pym ne sont pas compilés en baserel!

Enfin tu as compris... c'est super simple et cela m'a juste value quelques années de recherche et dévelopement.

Pour info: j'ai en plus ici passé sous silence comment j'exporte les variables globales entre la lib et le code l'utilisant! Tout une histoire... mais je sent que tout le monde est un peu fatigué avec un gros mal de crâne :-)
Yomgui Yomguiicon_post
Je viens de regarder un peu Pyrex: effectivement il ne prend pas en compte les spécificités de la version MorphOS.

en utilisant distutils pour compiler les modules on ne voit pas forcement du premier coup d'oeil qu'ils sont linkés avec la lib libpymX.Y.a.

Elle contient plus que les trampolines à l'API de Python: il y a plein d'autre trucs d'init/exit qui mettent en place le framework.
Et pour les exécutables pareil avec la libpythonX.Y.a : il y a du code comme dans la libauto.a, qui faudra refaire si on appel soit-même OpenLibrary() sur la python.library!!

Faut que je documente tout cela un de ces 4... :-D
--

http://blog.yomgui.fr/
http://www.yomgui.fr/yiki/doku.php
http://www.yomgui.fr/bugtracker
rmais96 rmais96icon_post
Si je comprends bien ce que tu essaies d'expliquer :

Le principe d'accès aux fonctions qui font partie de l'interface publique d'un 'type' Python n'est pas conçu pour permettre la préservation d'un registre processeur, alors que cela s'avère nécessaire sur MorphOS puisque Python utilise les librairies dynamiques (comme sur tout OS) et que le système de librairies dynamiques de MorphOS (hérité de l'AmigaOS) a besoin de cette préservation de registre.

Donc tout code Python qui importe un 'type' Python pour en utiliser les fonctions publiques va provoquer la modification du registre r13 sans en assurer la restauration après l'appel. Ce registre ayant perdu la base vers les données de la librairie Python, cela corrompt l'utilisation de cette librairie.

Du fait de la conception du système d'import des 'types' Python, il n'y a pas de solution simple pour remédier à cela, et c'est donc un problème qui remet en cause le support complet de Python sur MorphOS.

Pour l'instant, le code Python ou les 'type' Python que tu as compilés sur MorphOS tiennent compte de ce problème et tente d'y remédier en restaurant le registre r13. Mais tout code compilé sur un autre système et faisant usage de l'un 'type' lui-même compilé sur un autre système conduit inévitablement au problème sur MorphOS.

Est-ce bien cela que tu nous expliques ?
Yomgui Yomguiicon_post
A deux-trois termes près oui c'est cela.

On ne pas dire que le support complet de MorphOS est remis en cause.
Ce ne'est pas vrai, la base du langage supporte complètement MorphOS!
C'est quasiment que du C ANSI ! Après il y a quelques adaptation pour utiliser l'API MorphOS directement,
plutôt que de passer par des fonctions dans la libnix.
Evidement les modules c'est différent: il n'y a pas de support pour waitpid() et autre fork() par exemple.
C'est fait différement, c'est fait pour et dans l'espris AmigaEXEC.

Pour en revenir au sujet de ce registre r13: oui la régle d'or est d'avoir toujours ce registre valide avant l'appel à un quelconque morceau de code dans la lib python. D'où d'un côté mes histoires de 'trampolines' et de l'autre le fait de ne pas appeler une des fonctions exportées par les types: elles peuvent (à 99.99%) appeler elle aussi du code de la lib!

La seule façon de se passer d'une compilation en baserel et de ne plus avoir ce problème est d'utiliser une version statique de la lib... et donc devoir recompiler toutes les applications au moindre changement de la lib!! Totalement absurde!

Il faut savoir que les lib dynamique unix, windows et amiga fonctionne complétement différement les une des autres (celle de Windows se rapproche plus de celle de l'amiga).
Sous unix chaque chargement d'une lib dynamique provoque une copie de cette dernière. C'est ce que fait le mode baserel dans une certaine mesure, sous AmigaOS/MorphOS.
--

http://blog.yomgui.fr/
http://www.yomgui.fr/yiki/doku.php
http://www.yomgui.fr/bugtracker