Sujet: Expert: Les APIs en Rgss Ven 6 Fév 2009 - 15:46
Avertissement, ce tutoriel est destiné à des scripteurs avancés (mais après B ), comme je ne reprends pas les bases de ruby. Bon, mon objectif est dans un premier temps, de vous montrer la puissance des APIs, puis leur utilité, leur fonctionnement. Bref, de vous faire coder des scripts de sauvages !
Qu'est-ce qu'une API ?
Si Api est un dieu egyptien, c'est aussi un terme informatique. API est un acronyme de "Application Programming Interface". Si elles sont utilisées par toute sorte d'applications, on connait les APIs google, c'est parce que les APIs sont des fonctions publiées, exportées, par des programmes, OS... Vous avez déja rencontré des dll ! Ce sont des librairies (bibliothèrques) qui fournissent des éléments permmettant d'intégrer (interagir, modifier le comportement...) notre programme perso à un autre programme. C'est un énorme cadeau que nous file le programmeur ! Si certains programmes (compilés, donc 010011...) ne fonctionnent que sous windows et pas sur mac, ce n'est pas parce qu'ils ne sont matériellement incomptibles: tout ordinateur comprend des 0 et 1: c'est parce que le programme appelle des fonction intégrées à l'OS: les APIs. En gros, ce sont des portions de codes fournies, donc inutiles (et impossibles) à recopier dans notre script.
C'est bien, mais ca sert à quoi ?
Le ruby est un langage interprété, c'est à dire qu'il a besoin d'un autre programme compilé (01001...) pour fonctionner. Sa vitesse-exécution est donc bien plus lente qu'un autre programme compilé. Maintenant imaginez que l'on ait besoin de faire une capture d'écran de notre fenetre. Il faut capturer son contenu pixel par pixel, à l'aide d'une boucle for très laide. On peut utiliser alors une API ecrite en C donc rapide, pour arriver au même résultat: la fameuse dll screenshot. Ce n'est qu'une infime possibilité, je l'ai dit plus tôt, les apis (celles que nous utilisons sont des .dll ou .lib, donc exploitables que sous windows.) etablissent une interface avec l'OS.
Les APIs en RGSS
Ca devient interressant, maintenant. RGSS nous fournit une classe très pratique, la classe Win32API, c'est elle qui charge puis exécute les librairies. On la chareg comme ceci:
théoriquement toute librairie dll ou lib est utilisable: elle doit être placée à la racine du projet. Cependant, si vous êtes curieux, vous avez pu voir ou être forcé de voir en cas de bug, la quantité de librairies présentes dans le répertoire C:\WINDOWS\System32\. Vous en connaissez surement plusieurs. En voici une toute petite liste de celles que j'ai le plus souvent utilisées avec leur description:
user32.dll :interface utilisateur: ce qui interagit avec vous: les fenetres, le clavier, souris.
kernel32.dll :le noyaux de windows, les processus, mémoires...
Cette API affiche une boite de dialogue. Soit. Qu'est-ce que c'est que ce truc... Analysons pas à pas. Première ligne: l'initialisation:
Premier argument: 'user32' c'est le nom de la librairie que l'on utilise, l'extension '.dll' est optionnelle. C'est une chaîne.
Deuxième argument, la fonction: 'MessageBoxA'. c'est aussi une Chaîne. Chaque librairie comporte un certain nombre de fonctions, que l'on pourrait considérer comme nos méthodes ruby. C'est elle qui traitera l'action que l'on recherche.
Troisième argument: ['i','p','p','i'] c'est un tableau, mais cela peut très bien être une chaine: "ippi" ou un tableau de forme %w(i p p i). Ce sont des paramètres d'entrée. Je vous expliquerai après ce que ces lettres stupides représentent.
Dernier argument: 'i' c'est une chaîne, mais comme plus haut, cela peut être un tableau. C'est le valeur retournée par la fonction de la dll après l'exécution. Il y en a très souvent qu'une seule.
Deuxième ligne: l'exécution: Comme tout processus en ruby, l'appel se fait par la méthode .call de l'instance. Les arguments sont passés en entrée dans le tableau ['i','p','p','i']
Premier argument: 0 nombre entier (integer) correspond à 'i' : c'est l'adresse mémoire de la fenetre parente. On a mis 0 pour ne pas établir de parenté avec le Rgss Player.
Deuxième argument: 'texte' chaîne de caractères (string) : correspond à 'p' : c'est le contenu de la boite de dialogue.
Troisième argument: 'titre' chaîne de caractères (string) : correspond à 'p' : c'est le titre de la fenêtre.
Dernier argument: 1 nombre entier (integer) : ce sera le type de la fenetre (nombre de boutons, icones...).
Vous pouvez tester, une fenetre s'affiche... ouf !
Type d'arguments
Revenons à notre histoire de ippi... qu'est-ce que cela représente... Si vous avez fait du langage C, Basic, etc. vous devez savoir que toutes les variables n'ont pas la même déclaration. En ruby, même on distingue les float, des entiers, des strings. Et meme, dans les entiers, les Bignum et les autres. Ainsi, les paramètres sont traités différemment par ruby lors de leur envoi vers la dll. Voici leurs types:
i : integer: nombre entier : 0 254, -1.
l : long: nombre décimal, bignum: 0.254 et autres.
p : pointer: est utilisé pour les strings, mais aussi pour les données compactées en chaine (tableau...).
v : void: utilisé uniquement en retour de fonction retourne un nombre, mais on peut utiliser les autres.
et d'autres arguments moins utiles: n (nombre) et en ruby pur: s (string). Ainsi, pour chaque paramètre, il convient d'identifier son type.
Certaines APIS ont des arguements spéciaux, c'est à dire qu'il s'agit de faire passer plusieurs données dans un seul argument, comme un tableau, quoi ! Deux méthodes, qui ne sont pas applicables dans un meme cas, existent:
Les parenthèses: pour un groupe d'arguments de nombres:(1|254|2668|458) on utilise l'opérateur "OU bit par bit": "|" pour évaluer successivement les arguments, et les transférer s'ils sont exploitables.
Le compactage: il consiste a faire rentrer dans un string plusieurs données de type différent:
Code:
param=["arg",0,-1.25,"test"].pack("pilp")
param est maintenant une chaine
Arguments de retour
En général, la fonction renvoie 0 si son exécution a échoué, et un autre nombre non nul (utilisable: ex adresse mémoire d'une fenetre) en cas de réussite. il s'obtient par arg=api.call(...) Mais la fonction peut également renvoyer d'autres valeurs, par un moyen différent: aussi étrange que cela puisse paraitre, un argument d'entrée peut servir de valeur-sortie. prenons une api que vous avez surement rencontré : elle sert à récuperer le handle (adresse mémoire) de la fenetre de jeu, le Rgss Player.
que se passe-t-il? Dans un premier temps, on cherche à récuperer le titre de la fenêtre par GetPrivateProfileStringA , pour pouvoir l'identifier par une autre API FindWindowEx. On crée une chaine vide de 256 caractères nuls (\0 est un caractère nuls) qui contiendra le titre récupéré par l'API. La première API lit le fichier Game.ini, à la section Title et inscrit le titre récupéré dans la chaine préparée. En supprimant les caractères nuls, on obtient le titre en clair. Et on passe ce titre en paramètre à la seconde API qui identifie la fenetre en renvoie l'adresse mémoire. Parfois, on peut compacter un tableau en chaine, l'API modifiera et renverra cette chaine. On la dépactera pour en retrouver un tableau rempli ou modifié.
Trouver les arguments
Hé oui... je vous le laisse pour la fin... c'est ici la principale difficulté des APIs: on ne connait que le nom de la fonction, sans les arguments... comment les obtenir ? ben, il faut faire une recherche. Microsoft fournit un site très complet (un point pour lui, cette fois !) sur ses APIs: le site msdn. Tapez sur Google "msdn mafonction" vous tomberez sur une page en anglois détaillant la référence de la fonction. si l'on reprend notre API FindWindowEx: "msnd FindWindowEx" On peut s'y attarder, c'est super utile. Les fonctions sont expliquées dans le langage Basic ou C, parfois C#, il faut traduire le tout pour ruby. Descendez directement tout en bas de la page, vous y trouverez le nom de la dll. Remontez, vous voyez un encadré, avec comme titre Syntax: c'est l'appel de la fonction Le nom de la fonction est précédé d'un BOOL (0/1) VOID, HWND (handle)... c'est la valeur retournée. ici, c'est HWND Ensuite, suivent les arguments d'entrée: [TYPE, description]: HWND hwndParent : le handle du parent: le type vous aidera à trouver la lettre à écrire. ... Vous avez les explications des paramètres en dessous.
Précisions: Des constantes intégrées au C ou Basic sont parfois utilisées, vous en trouverez surement la valeur pour ruby en faisant une recherche ["NOM_CONST =" 0x4000] les guillemets forment un bloc pour la recherche google, le nombre hexadécimal trie les site affichant les valeurs des constantes
Ce tutoriel s'achève là... j'espère vous avoir appris quelque chose. Les APIs sont un outil très puissant, car rapide dans leur traitement, mais lent dans leur appel. Leur utilisation suppose pas mal de recherche, mais est à la hauteur du travail !
berka
Dernière édition par berka le Ven 6 Fév 2009 - 16:16, édité 1 fois
berka
Maire Lv.9
Age : 34 Inscrit le : 15/10/2008 Messages : 351
Sujet: Re: Expert: Les APIs en Rgss Ven 6 Fév 2009 - 15:48
Pour toutes questions, je suis là ! Au niveau des TPs... vous me direz s'il faut en faire !
yamazaki
Illusionniste Lv.12
Age : 34 Inscrit le : 27/12/2008 Messages : 757
Sujet: Re: Expert: Les APIs en Rgss Ven 6 Fév 2009 - 16:15
ne peut on pas inclure d'autre librairies pour ruby comme le Qt par exemple sous C++?? les Api sont vraiment trop compliqués
Dernière édition par yamazaki le Ven 6 Fév 2009 - 16:16, édité 1 fois
berka
Maire Lv.9
Age : 34 Inscrit le : 15/10/2008 Messages : 351
Sujet: Re: Expert: Les APIs en Rgss Ven 6 Fév 2009 - 16:15
si, il faut copier ta dll dans ton projet et trouver les bons arguments à appeler. mais apparemment tu n'as pas lu mon tuto avant de poser ta question.
yamazaki
Illusionniste Lv.12
Age : 34 Inscrit le : 27/12/2008 Messages : 757
Sujet: Re: Expert: Les APIs en Rgss Ven 6 Fév 2009 - 16:19
Comment retrouver le nom de la fonction qui permet de faire ce que l'on veut??
berka
Maire Lv.9
Age : 34 Inscrit le : 15/10/2008 Messages : 351
Sujet: Re: Expert: Les APIs en Rgss Ven 6 Fév 2009 - 16:26
normalement, quand tu sais ce que tu veux faire, tu trouves tout seul: trouver la position du curseur: getcurseur afficher/masquer une fenetre: showwindow... au pire, t'as un index sur msdn qui classe les fonctions par thème
msdn
ASHKA
Voyageur Lv.10
Age : 42 Inscrit le : 04/12/2008 Messages : 383
Sujet: Re: Expert: Les APIs en Rgss Ven 6 Fév 2009 - 16:29
Bah, Qt possede la doc la plus complete que je n'ai jamais vu. Tu ne va pas me dire que tu n'y trouve pas ce que tu veux ?
@berka : Cool, enfin, un tuto interessant, ça change !!
ASHKA
berka
Maire Lv.9
Age : 34 Inscrit le : 15/10/2008 Messages : 351
Sujet: Re: Expert: Les APIs en Rgss Ven 6 Fév 2009 - 16:31
Disons que ton MP m'a motivé pour faire ca !
merci !
yamazaki
Illusionniste Lv.12
Age : 34 Inscrit le : 27/12/2008 Messages : 757
Sujet: Re: Expert: Les APIs en Rgss Ven 6 Fév 2009 - 16:45
non je ne cherchais pas les fonctions de Qt mais plutôt celle des Api originelles de Windows
berka
Maire Lv.9
Age : 34 Inscrit le : 15/10/2008 Messages : 351
Sujet: Re: Expert: Les APIs en Rgss Ven 6 Fév 2009 - 16:59
d'où le :
Citation :
ne peut on pas inclure d'autre librairies pour ruby comme le Qt par exemple sous C++??
tout dépend du type de fenetre a afficher. Mais je n'ai fait que donner une base dans ce tuto, je vais pas vous prendre par la main pour vous trouver vos APIs. La recherche, c'est le boulot du maker !
MirainoHikari
Ex-Admin-Script
Age : 42 Inscrit le : 26/05/2008 Messages : 2360
Sujet: Re: Expert: Les APIs en Rgss Mar 10 Fév 2009 - 17:32
Désolé du retard, mais merci Berka. Pour les exercices, c'est à toi de voir. Ils ne sont pas inclus dans la feuilles de stats des membres car comme tu le dis, c'est pour les scripteurs plus avancé. Nous entrerons ça dans les atelier avancé. Mais tu pourrais donner des exemples concrèts avec un exemple de comment l'utiliser (sauf si tu veux te taper la correction d'exercices, dans ce cas, tu mes les exercices sans leur réponse).
La Meche
Flibustier Lv.21
Age : 30 Inscrit le : 24/05/2008 Messages : 3234
Sujet: Re: Expert: Les APIs en Rgss Mer 5 Aoû 2009 - 17:34
Désolé du gros nécropost mais j'ai un petit souci avec un retour de fonction Quand je fais
Code:
arg = api.call(...)
Après avoir déjà appelé la fonction
Code:
api.call(0, 'texte', 'titre', 1)
J'ai une Syntax error Et je pourtant j'ai fait comme dans l'exemple de berka...
Voici le code entier(Même si je pense il ne sert à rien >.>")
Code:
api = Win32API.new("user32",'MessageBoxA', ['i','p','p','i'], 'i') api.call(0, 'texte', 'titre', 1) arg = api.call(...) p arg
Sihn
Voyageur Lv.10
Age : 36 Inscrit le : 24/04/2009 Messages : 407
Sujet: Re: Expert: Les APIs en Rgss Mer 5 Aoû 2009 - 17:48
Je ne m'y connais pas particulièrement en api, mais je pense que ce code :
Code:
api = Win32API.new("user32",'MessageBoxA', ['i','p','p','i'], 'i') arg = api.call(0, 'texte', 'titre', 1) p arg
...marchera mieux.^^ Le call(...) voulait juste dire "remettez votre call ici". En gros, tu peux soit l'utiliser "brut" :
Code:
api.call(0, 'texte', 'titre', 1)
Soit en enregistrant le résultat dans une variable :
Code:
arg = api.call(0, 'texte', 'titre', 1)
(Mais que berka m'arrête si je me trompe!^^)
La Meche
Flibustier Lv.21
Age : 30 Inscrit le : 24/05/2008 Messages : 3234
Sujet: Re: Expert: Les APIs en Rgss Mer 5 Aoû 2009 - 17:52
Nan nan c'est ça ^^' Je viens à l'instant de trouver tout seul xD (En me souvenant d'un appelle de dll )
Merci beaucoup quand même ^^
A bientôt pour une prochaine question xD
berka
Maire Lv.9
Age : 34 Inscrit le : 15/10/2008 Messages : 351
Sujet: Re: Expert: Les APIs en Rgss Mer 5 Aoû 2009 - 20:18
C'est ca Sihn, sauf que la valeur retournée par l'appel d'api ne sert bien souvent à rien. Soit il renvoie 0: l'exécution a échoué, soit il renvoie un non nul: un handle (adresse mémoire). Ce handle peut etre utilisé par d'autres apis. Mais la plupart des structures de retour s'obtiennent par décompression de tableaux compactés et passés en paramètres.
berka
La Meche
Flibustier Lv.21
Age : 30 Inscrit le : 24/05/2008 Messages : 3234
Sujet: Re: Expert: Les APIs en Rgss Jeu 6 Aoû 2009 - 11:11
Bah dans ce cas :
Code:
api = Win32API.new("user32",'MessageBoxA', ['i','p','p','i'], 'i') arg = api.call(0, 'Voulez-vous lancer le jeu ?', 'Question', 4)
La valeur de retour est utile pour savoir quel choix à prit le joueur ! A moins qu'il n'existe un autre truc plus rapide ?