UML représentation pour le C/C++ pointeurs de fonction
Quelle serait la meilleure représentation d'un C/C++ pointeur de fonction (pf) dans un UML structurels diagramme?
Je suis en train de réfléchir à l'aide d'un élément de l'interface, peut-être, même si "dégénérée", avec la contrainte d'avoir plus qu'une seule opération déclarée.
J'ai trouvé une certaine proposition dans ce document: C et UML Synchronisation Guide de l'Utilisateur, Section 5.7.4. Mais cela semble assez lourd et pas très utile dans la pratique. Même si le droit d'un niveau très bas de vue sémantique. Voici un schéma présentant leur concept en bref:
À mon humble avis en C et C++ pointeurs de fonction sont utilisés en tant que tels une vision étroite d'une interface qui ne fournit qu'une seule fonction et de signature. En C fp serait également utilisé pour implémenter plusieurs interfaces complexes de la déclaration d'une structure contenant un ensemble de pointeurs de fonction.
Je pense que je peux même gérer pour obtenir mon outil UML particulier (Enterprise Architect) à l'avant de générer le code est correct, et la synchronisation avec les changements de code, sans préjudice.
Mes questions sont:
- Serait déclaration de la fp dans le cadre des éléments de l'interface UML fournissent une bonne vue sémantique?
- Ce genre de stéréotype doit être utilisé pour la fp déclaration? Au moins j'ai besoin de fournir une définition de type dans le code
ce serait donc mes tripes choix.(j'ai trouvé ce stéréotype est la propriété exclusive de Enterprise Architect) et j'ai besoin de préciser stéréotype pour obtenir la génération de code adapté. En fait, j'ai choisi le stéréotype nom de "délégué", est ce que cela a des conséquences ou de la sémantique des collisions? - Comme pour C++, serait imbrication d'un "délégué" sterotyped interface dans une classe d'élément suffisant pour exprimer une fonction membre de classe pointeur correctement?
Voici un exemple de diagramme de mes pensées pour le langage C de la représentation:
C'est le code C qui devraient être générés à partir du modèle ci-dessus:
struct Interface1;
typedef int (*CallbackFunc)(struct Interface1*);
typedef struct Interface1
{
typedef void (*func1Ptr)(struct Interface1*, int, char*);
typedef int (*func2Ptr)(struct Interface1*, char*);
typedef int (*func3Ptr)(struct Interface1*, CallbackFunc);
func1Ptr func1;
func2Ptr func2;
func3Ptr func3;
void* instance;
};
/* The following extern declarations are only dummies to satisfy code
* reverse engineering, and never should be called.
*/
extern void func1(struct Interface1* self, int p1, char* p2) = 0;
extern int func2(struct Interface1* self, char*) = 0;
extern int func3(struct Interface1* self, CallbackFunc p1) = 0;
EDIT:
Tout le problème se résume quelle serait la meilleure façon avec les UML outil à portée de main et son code spécifique à l'ingénierie. Ainsi, j'ai ajouté de l'entreprise-architecte de la balise.
- Une primitive de type de données si votre question est sérieuse, je l'ai mentionné ce (suivre le document lié).
- J'ai été très grave, mais en effet rhétorique et de ne pas se moquer de vous ou de quelqu'un d'autre. Je crois tout simplement que, parfois, nous devons revenir à l'essentiel.
- Au moins, j'étais confus lire l'allemand ici. Mais de toute façon, je ne vois que l'utilisation d'un uml:Type de données serait ressembler à ma proposition, malheureusement je ne peux pas imbriquer les Types de données à l'intérieur des classes avec mon outil UML (qui est probablement à droite) et aurait besoin de plus de typedefs, ce qui rend le diagramme de moins claire de son intention.
- Je dois corriger moi-même: Un pointeur de fonction n'est pas un <<primitive>> mais <<type>>.
- Je pense que cette approche est erronée dans le début. Pourquoi auriez-vous besoin de modèle de pointeur de fonction des objets?
- Principalement pour obtenir une granularité fine de contrôle sur la génération de code de l'outil UML, la curiosité est un autre aspect.
Vous devez vous connecter pour publier un commentaire.
EA fichier d'aide a ceci à dire sur le sujet de pointeurs de fonction:
Note "le plus possible." C'est à partir de la section C++, le C de l'article ne mentionne pas les pointeurs de fonction à tous. Donc ils ne sont pas bien pris en charge, qui à son tour est bien sûr en raison de l'écart entre la modélisation et de la programmation des communautés: non-trivial de langage ne sont tout simplement pas pris en charge dans UML, de sorte que toute solution, par nécessité, être d'outil spécifique.
Ma suggestion est un peu impliqué et c'est un peu hacky, mais je pense que cela devrait fonctionner assez bien.
Parce que dans UML opérations ne sont pas de première classe et ne peuvent pas être utilisés comme des types de données, ma réponse est de créer des entités de première classe pour eux - en d'autres termes, de définir le pointeur de la fonction de types de classes.
Ces classes servent à deux fins: le nom de la classe sera de refléter la fonction de la signature d'un type pour le faire paraître familier pour le programmeur dans les diagrammes de tout un ensemble de valeurs balisées représentera le paramètre effectif et types de retour pour une utilisation dans la génération de code.
0) Vous pouvez définir l'un des OMD de la Technologie pour les étapes 1 à 4.
1) Définir une tagged value type "retval" avec le Détail "Type=RefGUID;Valeurs=Classe;"
2) Définir un ensemble de tagged types de valeur avec le même Détail nommé "par1", "par2" et ainsi de suite.
3) Définir un profil avec une Classe de stéréotype "funptr" contenant un "retval" tagged value (mais pas de "par" tags).
4) Modifier le code de génération de scripts de Déclaration d'Attribut et de Paramètre pour récupérer le "retval" (toujours) et "par1" - "parN" (où elle est définie) et de générer de la syntaxe correcte pour eux. Ce sera le moment difficile et je n'ai pas réellement fait. Je pense qu'il peut être fait sans trop d'effort, mais vous aurez à essayer. Vous devez également vous assurer qu'aucun code n'est généré pour "funptr" les définitions de classe, car ils représentent des types anonymes, pas typedefs.
5) Dans la cible de votre projet, de définir un ensemble de classes pour représenter la primitive C types.
Avec cela, vous pouvez définir un pointeur de fonction de type «funptr» de la classe avec un nom comme "long(*)(char)" pour une fonction qui prend un char et renvoie une longue.
Dans le "retval" étiquette, sélectionnez l'option "longtemps" la classe que vous avez défini à l'étape 4.
Ajouter le "par1" tag manuellement, et sélectionnez le "char" de la classe comme ci-dessus.
Vous pouvez maintenant utiliser cette classe comme le type d'un attribut ou d'un paramètre, ou n'importe où ailleurs où EA permet à une catégorie de référence (comme dans le "par1" balise d'un autre «funptr» classe; cela vous permet de créer facilement des types de pointeur pour les fonctions où l'un des paramètres est lui-même d'une fonction de type pointeur).
La hackiest peu ici, c'est le numéro "par1" - "parN" balises. Alors qu'il est possible d'EA de définir plusieurs tags avec le même nom (vous pouvez avoir à changer la tagged value options de la fenêtre pour les voir), je ne pense pas que vous pourriez récupérer les différentes valeurs de la génération de code de script (et même si tu le pouvais, je ne pense pas que l'ordre serait nécessairement être préservée, et l'ordre des paramètres est important dans C). Donc, vous devez décider le nombre maximal de paramètres à l'avance. Pas un énorme problème dans la pratique; la mise en place dire 20 paramètres doivent être beaucoup.
Cette méthode est d'aucune aide pour l'ingénierie inverse, ie 9 ne vous permet pas de personnaliser le reverse-engineering de processus. Cependant, la prochaine EA 10 (actuellement en RC 1) permettra de cela, bien que je n'ai pas regardé moi-même donc je ne sais pas quelle forme cela va prendre.
par1
àparN
balises doit avoir une certaine limitation dans le nombre qui auront à appliquer dans le modèle de génération de code.<<funptr>>
puis-je (dois-je) de l'accès de rien d'autre que le nom de la classe? Pour l'instant, je suis juste en utilisant un nom de classe et de remplacer le(*)
avec(*<param/attr-name>)
, également très orthodoxe ...La définition de pointeurs de fonction est en dehors de la portée de la spécification UML. Ce qui est plus, il est spécifique à la langue fonctionnalité qui n'est pas pris en charge par de nombreux modélisation UML logiciel. Donc, je pense que de manière générale, la réponse à votre première question suggère d'éviter de cette fonctionnalité. Les astuces que vous avez fournies sont pertinentes à l'Architecte d'Entreprise et ne sont pas compatibles avec d'autres outils de modélisation UML. Voici comment pointeurs de fonction est prise en charge dans certains autres UML du logiciel:
MagicDraw UML utilise <<
C++FunctionPtr
>> les stéréotypes en PF pour les membres de la classe et <<C++FunctionSignature
>> pour le prototype de fonction.Échantillon de code (prises de site officiel -- voir "Modélisation de la définition de type et de pointeur de fonction pour la génération de code C++" animations montrant):
Correspondant UML modèle:
Objecteering définit FP attributs avec C++ correspondante TypeExpr note.
Rational Software Architect d'IBM ne supporte pas les pointeurs de fonction. L'utilisateur peut ajouter le code généré par l'utilisateur défini des sections qui ne sont pas touché au cours de code->UML et UML->code des transformations.
Semble correct pour moi. Je ne suis pas sûr que vous devez plonger dans les détails de bas niveau de descripting le type et la relation de votre pointeur de fonction. J'ai l'habitude de trouver que la description d'une interface assez de détails sans la nécessité de décomposer les éléments internes d'elle.
Je pense que vous pourriez pratiquement envelopper le pointeur de fonction à une classe. Je pense que UML n'a pas à être blueprint niveau du code, la documentation, le concept est plus important.
Mon sentiment est que vous avez le désir de carte UML interfaces de la structure-avec-fonction-les pointeurs C idiome.
Interface1 est l'élément important de votre modèle. Déclarer le pointeur de la fonction des types d'objets tous plus de la place feront de vos diagrammes illisible.
Enterprise Architect permet de spécifier vos propres générateurs de code. Recherchez les Code Modèle Cadre. Vous devriez être en mesure de modifier la préexistants générateur de code C à l'aide d'un nouveau stéréotype ou deux.
UML:dataType
, qui est finalement le "droit chemin" à mon humble avis. Mais j'ai des difficultés pour obtenir cette vue manipulé droit avec EA génération de code et la rétro-ingénierie des installations. C'est pourquoi, au moins, j'ai décidé d'aller avec Uffe de la proposition, car il fournit la "meilleure" façon d'utiliser pour EA C/C++ modèles de la classe et donne un bon indicateur visuel dans l'affichage du pc utilisés en tant que paramètres ou des attributs.J'ai été en mesure d'obtenir quelque chose de la sorte de travail avec l'Architecte d'Entreprise. C'est un peu d'un hacky solution, mais il répond à mes besoins. Ce que j'ai fait:
Créer une nouvelle classe de stéréotype nommé FuncPtr. J'ai suivi le guide ici: http://www.sparxsystems.com/enterprise_architect_user_guide/10/extending_uml_models/addingelementsandmetaclass.html
Quand j'ai fait ce que j'ai fait une nouvelle vue pour le profil de. Donc, je peux le garder à l'extérieur de mon projet principal.
Modifié le code de Catégorie de modèles. Fondamentalement, la sélection du langage C et de commencer avec le Modèle de Classe et cliquez sur "Ajouter un Nouveau Stéréotype Remplacer" et d'ajouter " dans FuncPtr comme un nouveau remplacement.
Ajouter dans le code suivant pour que le nouveau modèle:
Modifié la Déclaration d'Attribut modèle de code. Même façon que précédemment, l'ajout d'un nouveau Stéréotype
Ajouter le code suivant dans le nouveau modèle:
C'est tout ce que j'avais à faire pour obtenir des pointeurs de fonction en place dans Enterprise Architect. Quand je veux définir un pointeur de fonction je viens de:
De cette manière, il va créer un nouveau type peuvent être inclus en tant qu'attributs ou des paramètres dans d'autres classes (les structures), et des opérateurs. Je n'ai pas l'exploitant lui-même, car alors il n'aurait pas été référencés à l'intérieur de l'outil comme un type que vous pouvez sélectionner.
De sorte que son très orthodoxe, à l'aide de classes stéréotypées que les typedefs à des pointeurs de fonction.
Comme votre premier exemple que j'utilise un Classificateur mais la cacher au loin, dans un profil. Je pense qu'ils ont compris pour la clarté de l'explication du concept; mais, dans la pratique, l'idée de stéréotypes est abstraire les détails dans les profils d'éviter le "bruit" problème. EA est assez bon pour la manipulation des Profils.
Où je diffère de votre premier exemple est que je voudrais Classer les Type Primitif Stéréotype pas le Type de Données stéréotype. Type de données est un Domaine de la portée de l'objet, tandis que le Type Primitif est atomique de l'élément avec la sémantique définie en dehors de la portée de l'UML. Ce n'est pas à dire que vous ne pouvez pas ajouter des notes, en particulier dans le profil ou lui donner un très clair stéréotype nom comme functionPointer.