Implémenter des méthodes pour des versions antérieures de MacOS
Chacha
Membre
Salut,
Sous MacOS 10.4, la méthode objectsAtIndexes: de NSArray est bien pratique.
Elle n'existe pas sous MacOS 10.3. Elle est facile à réimplémenter.
Je pourrais faire un wrapper myObjectsAtIndexes: (dans une catégorie de NSArray) qui appelle objectsAtIndexes: sous 10.4 et mon code sous 10.3, mais je trouve ça un peu dommage de devoir utiliser un autre nom.
Y a-t-il moyen de faire en sorte qu'une (re)définition de objectsAtIndexes ne soit "vue" que sous 10.3, sans faire des tests à chaque appel ? Et que ça compile sans warnings ?
+
Chacha
Sous MacOS 10.4, la méthode objectsAtIndexes: de NSArray est bien pratique.
Elle n'existe pas sous MacOS 10.3. Elle est facile à réimplémenter.
Je pourrais faire un wrapper myObjectsAtIndexes: (dans une catégorie de NSArray) qui appelle objectsAtIndexes: sous 10.4 et mon code sous 10.3, mais je trouve ça un peu dommage de devoir utiliser un autre nom.
Y a-t-il moyen de faire en sorte qu'une (re)définition de objectsAtIndexes ne soit "vue" que sous 10.3, sans faire des tests à chaque appel ? Et que ça compile sans warnings ?
+
Chacha
Connectez-vous ou Inscrivez-vous pour répondre.
Réponses
MyArray.m :
En effet, mon but est de ne générer qu'un exécutable, compilé avec le MacOSX10.4u.sdk, mais qui fonctionne sous Panther.
+
Chacha
??
Un exécutable compilé avec "MacOSX10.4u.sdk" n'est pas vraiment fait pour tourner sous Panther... C'est assez hasardeux comme technique
Si tu veux générer un seul exécutable, c'est compilé avec "MacOSX10.3.9.sdk", ce qui donnera un exécutable PPC qui tournera avec Rosetta sur les Mac Intel
Une bonne configuration 10.3/10.4 Intel/PPC, c'est :
SDKROOT_i386 = /Developer/SDKs/MacOSX10.4u.sdk
SDKROOT_ppc = /Developer/SDKs/MacOSX10.3.9.sdk
Si tu as un seul exécutable, il sera soit PPC, soit Intel, non ??
Je pense que ça doit marcher du moment qu'on n'appelle que des méthodes disponibles sous Panther. Apparemment, MacOS 10.3 lit la partie PPC des binaires universels sans problème (c'est ce que j'ai fait pour RubyCalc
http://www.objective-cocoa.org/forum/index.php/topic,2101.0.html)
+
Chacha
Oui, mais c'est hasardeux et dangereux...
De toute manière, si tu as un binaire universel, tu as deux compilation et deux exécutables, donc je ne vois pas l'intérêt de créer la partie PPC avec /Developer/SDKs/MacOSX10.4u.sdk au lieu de la créer avec /Developer/SDKs/MacOSX10.3.9.sdk ???
Je vais expliciter plus...
Là , tu penses ne pas utiliser des fonctions "10.4", mais il est possible que certaines fonctions du SDK 10.3.9 aient été mises à jour dans le SDK 10.4u en appelant des fonctions 10.4u tout en gardant le même nom.
Que se passe-il dans ces cas là ?
Utiliser le SDK 10.3.9 permet justement de garder une cohérence tout le long et d'éviter ça !
Qu'est-ce qui risque de se passer ?
[grillé]
Si je compile avec le 10.3.9.sdk, le code PPC peut-il bénéficier des méthodes de l'AppKit 10.4 ?
C'est là que ça devient complexe... :crackboom:-
À priori... non. Après, il y a peut-être moyen de bidouiller, mais à mon avis c'est grosse prise de tête !
En général, les développeurs qui veulent faire profiter des nouveautés à leur application maintiennent deux versions (voire plus).
(en agrémentant le code source de quelques #if et en créant plusieurs "targets")
Ben alors c'est pas aujourd'hui que je vais unifier LaTeXiT ! Bah, tant pis.
Merci quand même
+
Chacha
À ce qu'il me semble Mach-O est prévu (depuis OpenStep) pour contenir des exécutables pour plusieurs platteformes différentes (OpenStep tournait sur i386, 68k, sparc, dec-alpha et j'en passe). La possibilité a donc toujours existé sous OS X, mais n'a pas été "dévoilée" parce que OS X ne tournait jusqu'il y a peu que sur une platteforme. Maintenant, lorsqu'on fait un UB on fait 2 compils différentes, donc je ne vois pas où est le souci d'en faire une pour 10.3/ppc et une pour 10.4/intel (je ne vois pas d'autre solution "propre"). C'est en tous cas ce qui est suggéré ici:
http://www.zengobi.com/blog/2006/03/details-on-our-universal-binary-port.html
Mais l'inconvénient de cette méthode est que les 10.4/ppc ne peuvent pas "profiter" de l'implémentation Apple des méthodes que tu as réimplémenté. Il te faut ensuite faire des "lazy bindings" des framework qui ont été ajoutés dans Tiger, les charger à la volée et faire des tests au run time pour que les 10.4/ppc puissent profiter des nouveautés de 10.4.
Oui da, c'est exactement ce que j'ai ditÂ
Pas plus, pas moins...
Ce qui est dangereux, c'est de laisser 10.3 taper dans du code PPC généré avec le SDK 10.4u, donc un tout autre sujet !
(ça contient des exécutables pour plusieurs "plates-formes" différentes, mais pas pour plusieurs "OS" différents !)
D'où l'intérêt de maintenir éventuellement des versions avec des fonctionnalités ajoutées venant des SDK récents avec une "target" spéciale 10.4 par exemple...
(par contre, il faut barder le code de #if au niveau de ces fonctionnalités supplémentaires...)
En y réfléchissant plus, en faisant super-attention, ça devrait pouvoir fonctionner car il appellera ces fonctions sur le code Framework de la machine, donc pas de risque qu'il tape dans une fonction mise à jour.
À voir... Un peu hasardeux quand même je pense.
À voir déjà si 10.3 accepte sans sourciller un code compilé avec le SDK 10.4u
Oui, j'ai fais ainsi pour mon GPB et ça fonctionne très bien, il se porte comme un charme sur les deux versions.
Peut-être en sous-classant NSArray, en redéfinissant "objectsAtIndexes" de manière à appeler la classe mère sous 10.4 et l'implémenter sous 10.3, puis utiliser "poseAsClass"...
En fait, je pense à une autre méthode qui mélange la fonction sel_registerName et le method swizzling...
Premièrement, via une catégorie, faut créer une méthode simulant la méthode manquante (mais avec un autre nom) : par exemple objectsAtIndexes_10_3:.
Secondo, au tout début du programme (soit dans le main, soit dans un delegate de fin de chargement de NSApplication), il faut tester la présence de la méthode objectsAtIndexes:, et si elle n'existe pas, alors faire un sel_registerName("objectsAtIndexes:");.
Enfin via le truc du method swizzling de Chacha (voir ce post), récupérer le pointeur de la méthode objectsAtIndexes_10_3: pour l'injecter dans la méthode créée par sel_registerName.
Bon, ce n'est que de la théorie, mais ça vaut le coup d'essayer.
.
J'attends avec impatience les conclusions. Au passage, je signale que le poseAsClass: marche bien et devrait marcher dans ce cas. La seule limitation est qu'on ne peut pas ajouter d'ivar dans la classe de substitution.
Quand on aura trouvé comment rétro-implémenter une méthode , on pourra alors essayer de le faire mais pour une classe entière. Je me casse les octets depuis des semaines en essayant de ré-implémenter NSPredicate pour 10.3, sans succes. Alors je pose une option dès à présent sur ce problème, sachant que la solution devrait découler de celle au problème de ce fil.
objectsAtIndexes_10_3: est la méthode de remplacement de objectsAtIndexes:. Elle doit être définie dans une catégorie de NSArray. Bien sûr, la méthode remplaçante doit avoir exactement la même signature que la méthode à ré-implanter.
Voilà , en fait c'est plus simple que je le pensais.
Vraiment, le runtime de ObjC est incroyablement flexible !
.
Cela m'amène une question. Cette souplesse n'est-elle pas potentiellement dangereuse niveau sécurité?
À priori pas... Les droits sont bien cloisonnés dans un système basé "Unix".
Salut,
Effectivement, même si j'avais pensé sortir le swizzle, je n'avais pas vraiment trouvé comment m'en servir. Ta solution est intéressante !
Merci
+
Chacha