[Résolu] Appeler une fonction à partir d'une chaîne de ...

Xorgnem
[Résolu] Appeler une fonction à partir d'une chaîne de ...

Bonjour, actuellement en stage, je bloque sur une fonctionnalité de mon projet en C++.

Je recois un message en string ou en char*, je l'analyse pour en tirer un nom d'une fonction, et des eventuels parametres.
Par exemple je recupère le nom function1 et le paramétre int 128.
J'ai alors tout ce qu'il me faut pour appeler la fonction function1(128); mais il reste le problème que c'est une chaine de caractères. Donc je cherche quelque chose qui me permettra a aprtir de cette chaine a appeler une fonction (biensur predefinie)

Pouvez-vous m'aider?

Merci pour vos reponses

K-lo

Une question : la fonction appartient au projet ou alors la fonction est plutôt un exécutable => lancement d'un autre programme ?

Xorgnem

Les fonctions que je dois appeler ne sont pas des executables.
Et ca doit tourner sous Windows CE. (GetprocAddress o LoadLibreary n'iront pas je pense)
Il y a bien l'idee du map, mais est fastidieuse, car trop de fonctions..., j'ai entendu parler de RTTI ... j'essaye de trouver des infos dessus...

fredericmazue

Quote:
Et ca doit tourner sous Windows CE. (GetprocAddress o LoadLibreary n'iront pas je pense)

Et pourquoi pas ?

Quote:
Il y a bien l'idee du map,

C'est bien ce qu'il faut faire.

Quote:
mais est fastidieuse,

Oui...
[private joke]C++ n'est pas Lisp ;) [/private joke]

Quote:

j'ai entendu parler de RTTI ... j'essaye de trouver des infos dessus...

Te fatigue pas. RTTI ne fait rien d'autre que de te bricoler un char* sur l nom du type, autrement dit moins que ce que tu as déjà avec le nom de la fonction :D
Tu ne pourras pas t'en servir pour appeler une fonction. Car tu n'auras pas accès au pointeur.
Exemple:

int double_int(int i)
{
	return 2*i;
}

cout << typeid(double_int).name() << endl; // imprime le char*

imprime:

int __cdecl(int)

En plus non seulement ce n'est pas portable, mais c'est dépendant de l'implémentation, donc variable même d'un compilateur à l'autre. Même d'une version d'un compilateur à la version suivante. Et même, si on prend le standard à la lettre, variable d'une compilation à l'autre :lol:

Quote:

18.5.1-1
The class type_info describes type information generated by the implementation. Objects of this class
effectively store a pointer to a name for the type, and an encoded value suitable for comparing two types for
equality or collating order. The names, encoding rule, and collating sequence for types are all unspecified
and may differ between programs.

Tu vas devoir t'embêter avec les map....
Ou peut être repenser le code.
Comment en es tu arrivé là ?

Xorgnem

Dans la doc de GetProcAddress et LoadLibrary, c'est bien mentionné que l'on ait Windows vista ou xp ou Me ou 98 ou 95. Pas de win CE.
Mais on m'a conseillé de le tenter, je vais voir..

et j'en suis arrivé là tout simplement parce aue je suis en stage et que je reprends qqch d'existant. Mon maitre de stage m'a dit qu'il voulait pouvoir appeler des fonctions depuis l'exterieur du systeme, par l'envoi de messages generiques (ces messages etant une chaine de caracteres contenant nom de la fonction et parametres) je l'ecoute a la lettre :)

Xorgnem

Ca a l'air de fonctionner le getProcAddress !
Il reste maintenant a appeler la fonction et lui passer des parametres a partir de son adresse
Merci pour votre aide :lol:

fredericmazue

Quote:
je l'ecoute a la lettre

Est-ce bien raisonanble ? ;)
Quote:
Ca a l'air de fonctionner le getProcAddress

Il ny' a pas de raison.
Quote:
Il reste maintenant a appeler la fonction et lui passer des parametres a partir de son adresse Aucune difficulté

Je reprends mon exemple de fonction.

int double_int(int i) 
{ 
   return 2*i; 
} 

d'abord définir un synonyme pour le type de pointeur de fonction (c'est plus pratique):

typedef int *(pfn) (int);

ensuite une variable pour ranger le pointeur

pfn le_pointeur;

Ensuite récupérer le pointeur

le_pointeur = (pfn)GetProcAddress(handle_librairie, TEXT("double_int"));

Et enfin appel

int result = le_pointeur(128);

J'ai écrit ça très vite (pas le temps et fatigué ce soir) mais je pense que ça devrait aller :)

K-lo

msdn wrote:
LoadLibrary

Maps the specified executable module into the address space of the calling process.

For additional load options, use the LoadLibraryEx function.

HMODULE WINAPI LoadLibrary(
  LPCTSTR lpFileName
);

Parameters

lpFileName
[in] Pointer to a null-terminated string that names the executable module (either a .dll or .exe file).

Et si on veut lancé une appli plutot qu'une fonction on utilise LoadLibrary(..)

Mais comment faire cela si on veux que le programme se lance en tâche de fond (sans voir le déroulement de l'application appelée)?

fredericmazue

Quote:
Et si on veut lancé une appli plutot qu'une fonction on utilise LoadLibrary(..)

La fonction n'est pas "lancée". Avec LoadLibrary, la dll est seulement chargée dans la mémoire du processus... qui la charge et qui est le "calling process", c'est à dire le processus qui appelle l'API LoadLibrary.
Après ça GetProcAddress permet d'obtenir l'adresse d'une fonction dans cette dll. Le proc de GetProcAddress veut dire procédure, pas process :)

Quote:
Mais comment faire cela si on veux que le programme se lance en tâche de fond

Sous Windows on utilise l'infâme API CreateProcess.
Mais le mieux (le plus facile et direct, sans mettre tes mimimes dans le cambouis de CreatePorcess) est encore de passer par les fonction Posix de ton compilo: execv et compagnie. Vois dans ta doc.
K-lo

C'est vraiment une catastrophe le windows. Ca me rappel les MFC

execv ? Mais ça me rappel les bons souvenir où je codais sous linux en cours ça :D
pff je devrait essayer de revoir mes bases moi tiens...

Merci.

fredericmazue

Quote:
C'est vraiment une catastrophe le windows. Ca me rappel les MFC

D'autant mieux que les MFC ne sont qu'une très fine couche sur les APIs Windows :lol:
Et oui, les APIs Windows sont une catastrophe. En plus il y a le standard Posix. Mais Kro$soft se fait bien entendu une règle de ne pas l'appliquer :cry:
Quote:
Mais ça me rappel les bons souvenir où je codais sous linux

Je pense bien puisque ce sont des fonctions Posix donc standards. Pour t'éviter de chercher, sous Linux, tu vas les trouver déclarées dans unistd.h comme il se doit. Ce ne sont alors pas des fonctions de ton compilo comme dis dans mon post précédent, mais bien des fonctions système.

Mais en principe les compilos windows fournissent une implémentation. Par exemple tu vas les trouver sous Visual 6.0. Sous Visual 2005, c'est autre chose, tu vas voir dans la doc:

Quote:
This POSIX function is deprecated beginning in Visual C++ 2005. Use the ISO C++ conformant _execv instead

Avec un pipeau équivalent pour les fonctions C telles strcpy, etc.
Sauf que les fonctions n'ont jamais été déclarées dépréciées par les standard C ou C++. Là je parle "strcpy". Quant aux execv et compagnies elles ne sont pas dans le standard C puisque ce sont des fonctions standard Posix.

Mais bref, Microsoft a unilatéralement décidé d'affirmer que tout un paquet de fonctions sont dépréciées dans son 2005. Ce qui est proprement un scandale. D'ailleurs il y a eu des échange de gros mots au comité C++, à cause de cette politique, à l'encontre des types de kro$oft. Le "déprécié" est la version édulcorée que ce que Kro$oft avait l'intention de faire, mais vu la volée de bois vert qu'ils ont pris, ils sont un peu revenus en arrière.
Quant à moi, comme d'autres, je boycotte ce compilateur depuis que je suis tombé sur ça. Dans des entreprises, c'est tout une affaire pour avoir l'autorisation de supprimer un warning. Et je ne parle même pas d'envisager d'utiliser les versions Kro$oft des fonctions.... c'est hors stadard, donc NIET! Si j'utilise Visual 2005 en C++ c'est avec un autre compilateur C++. Et puis bof, parce que j'ai Emacs aussi sous Windows :)

Bon je me suis un peu éloigné du sujet, mais ça soulage, et ça ne fait pas non plus de mal de rétablir un peu la vérité.

K-lo

Quote:
Bon je me suis un peu éloigné du sujet, mais ça soulage, et ça ne fait pas non plus de mal de rétablir un peu la vérité

Bien dit :D

Bon je sais ce qui me reste a faire faire comme un programmeur : remettre en question certaines choses
Résultat :
-revoir les standards posix
-utiliser BOOST, QT, un peu de la STL

et avec ça je devrais pouvoir faire du code plus souple que les APIs "usine à gaz" de Kro$oft...

Quote:
Et puis bof, parce que j'ai Emacs aussi sous Windows Smile
Aaaaaah ce bon vieux Emacs :D

Mais revenons au problème Xorgnem... As tu résolu complètement ton problème ? Si oui peux tu éditer ton titre de sujet en rajoutant "[résolu]"

fredericmazue

Quote:
un peu de la STL

Puis je me permettre ? *** beaucoup *** la stl
Quote:
Aaaaaah ce bon vieux Emacs

Y a que ça de vrai :)

Quote:
Mais revenons au problème Xorgnem... As tu résolu complètement ton problème ? Si oui peux tu éditer ton titre de sujet en rajoutant "[résolu]"

Ce n'était pas mon problème remarque bien :)
Mais on peut le considérer comme résolu à priori.
Si Xorgnem ne l'indique pas, je le ferai moi même... comme d'hab ... :(