C / C ++函数指针的UML表示 [英] UML representation for C/C++ function pointers

查看:117
本文介绍了C / C ++函数指针的UML表示的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在UML结构图中最好地表示C / C ++函数指针(fp)?



我正在考虑使用接口元素,即使在退化的情况下,最多只能声明一个操作。



我在本文档中找到了一些建议:。但这听起来很麻烦,在实践中不是很有用。即使从非常低的语义角度来看也是如此。这是简要说明其概念的图:


C和C ++函数指针中的

IMHO用作接口的缩小视图,该接口仅提供单个函数及其签名。在C中,fp还可以用于实现更复杂的接口,声明一个包含一组函数指针的结构。



我想我什至可以设法得到自己的特定UML工具(企业架构师)向前生成正确的代码,并与代码更改同步而无害。



我的问题是:


  1. 将fp声明为接口元素的一部分在UML中提供正确的语义视图?

  2. 单个fp声明应使用哪种构造型?至少我需要在代码中提供一个typedef,所以这是我的勇气选择。(我发现此构造型是Enterprise Architect专有的),并且我需要定义一个适当的构造型以使代码生成适应。其实我已经选择了原型名称'delegate',这是否有任何含义或语义冲突?

  3. 对于C ++,将在类元素中嵌套足够的 delegate定型接口正确表达类成员函数指针?

下面是我对C语言表示的看法的示例图:



这是C应该从以上模型生成的代码:

  struct Interface1; 

typedef int(* CallbackFunc)(struct Interface1 *);

typedef struct Interface1
{
typedef void(* func1Ptr)(struct Interface1 *,int,char *);
typedef int(* func2Ptr)(结构接口1 *,char *);
typedef int(* func3Ptr)(结构接口1 *,CallbackFunc);

func1Ptr func1;
func2Ptr func2;
func3Ptr func3;

void *实例;
};

/ *以下extern声明只是满足代码
*逆向工程的虚拟变量,决不能调用。
* /
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;

编辑:

整个问题归结为什么是使用UML工具及其特定代码工程功能的最佳方法。因此,我添加了
enterprise-architect 标记。

解决方案

EA的帮助文件中关于函数指针的主题有以下说法:


导入C ++源代码时,Enterprise Architect将忽略函数指针声明。要将它们导入模型,您可以创建一个typedef来定义一个函数指针类型,然后使用该类型声明函数指针。以这种方式声明的函数指针将作为函数指针类型的属性导入。


注意可能。这是来自C ++部分,C部分根本没有提到函数指针。因此,它们没有得到很好的支持,这当然是由于建模和编程社区之间的鸿沟:UML根本不支持非平凡的语言概念,因此任何解决方案都必须是特定于工具的。 p>

我的建议有点复杂,有点怪异,但我认为它应该很好用。



因为在UML中操作不是一流的,并且不能用作数据类型,所以我的响应是为其创建一流的实体-换句话说,将函数指针类型定义为类。



这些类将有两个作用:类名将反映函数的类型签名,以使程序员在图中熟悉它,而一组标记值将代表实际的参数并返回函数的类型。



0)。您可能想为步骤1-4设置MDG技术。



1)使用以下命令定义标记值类型 retval Detail Type = RefGUID; Values = Class;



2)定义另外一组带有相同Detail的标记值类型,分别命名为 par1, par2和



3)定义一个配置文件,该配置文件的类构造型为 funptr,其中包含 retval标记的值(但不包含 par标记)。



4)修改代码生成脚本的属性声明和参数,以检索 retval(始终)和 par1- parN(已定义)并为其生成正确的语法。这将是棘手的事情,而我实际上还没有做到这一点。我认为无需过多的努力就可以完成,但是您必须尝试一下。您还应该确保不会为 funptr类定义生成任何代码,因为它们代表匿名类型,而不是typedef。



5)在目标项目中,定义一个集合表示原始C类型的类。



有了这个,您可以将函数指针类型定义为«funptr»类,其名称类似于 long(*)(



在 retval标记中,选择在步骤4中定义的 long类。 / p>

手动添加 par1标签,然后选择上面的 char类。



您现在可以使用此类作为属性或参数的类型,或在EA允许类引用的任何其他位置(例如在不同的«funptr»类的 par1标签中使用);这使您可以轻松地为函数创建指针类型参数本身就是函数指针类型。)



这里最讨厌的位是编号的 par1- parN标签。尽管可以在EA中定义多个具有相同名称的标签(您可能必须更改标记值窗口选项才能看到它们),但我认为您无法在代码生成脚本中检索不同的值(即使您可能不认为必须保留顺序,并且参数顺序在C中很重要)。因此,您需要事先确定最大参数数量。在实践中不是一个大问题;设置说20个参数应该足够。



此方法对逆向工程没有帮助,因为EA 9不允许您自定义逆向工程过程。但是,即将推出的EA 10(当前在RC 1中)将允许这样做,尽管我自己没有亲自看过,所以我不知道它将采用什么形式。




What would be the best representation of a C/C++ function pointer (fp) in an UML structural diagram?

I'm thinking about using an interface element, may be even if 'degenerate' with the constraint of having at most a single operation declared.

I found some proposal in this document: C and UML Synchronization User Guide, Section 5.7.4. But this sounds quite cumbersome and not very useful in practice. Even if right from a very low level of semantic view. Here's a diagram showing their concept briefly:

IMHO in C and C++ function pointers are used as such a narrowed view of an interface which only provides a single function and it's signature. In C fp's would be used also to implement more complex interfaces declaring a struct containing a set of function pointers.

I think I can even manage to get my particular UML tool (Enterprise Architect) to forward generate the correct code, and synchronizing with code changes without harm.

My questions are:

  1. Would declaration of fp's as part of interface elements in UML proivde a correct semantic view?
  2. What kind of stereotype should be used for single fp declaration? At least I need to provide a typedef in code so this would be my guts choice.(I found this stereotype is proprietary for Enterprise Architect) and I need to define an appropriate stereotype to get the code generation adapted. Actually I have chosen the stereotype name 'delegate', does this have any implications or semantic collisions?
  3. As for C++, would be nesting a 'delegate' sterotyped interface with in a class element enough to express a class member function pointer correctly?

Here's a sample diagram of my thoughts for C language representation:

This is the C code that should be generated from the above model:

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:
The whole problem boils down what would be the best way with the UML tool at hand and its specific code engineering capabilities. Thus I have added the tag.

解决方案

EA's help file has the following to say on the subject of function pointers:

When importing C++ source code, Enterprise Architect ignores function pointer declarations. To import them into your model you could create a typedef to define a function pointer type, then declare function pointers using that type. Function pointers declared in this way are imported as attributes of the function pointer type.

Note "could." This is from the C++ section, the C section doesn't mention function pointers at all. So they're not well supported, which in turn is of course due to the gap between the modelling and programming communities: non-trivial language concepts are simply not supported in UML, so any solution will by necessity be tool-specific.

My suggestion is a bit involved and it's a little bit hacky, but I think it should work pretty well.

Because in UML operations are not first-class and cannot be used as data types, my response is to create first-class entities for them - in other words, define function pointer types as classes.

These classes will serve two purposes: the class name will reflect the function's type signature so as to make it look familiar to the programmer in the diagrams, while a set of tagged values will represent the actual parameter and return types for use in code generation.

0) You may want to set up an MDG Technology for steps 1-4.

1) Define a tagged value type "retval" with the Detail "Type=RefGUID;Values=Class;"

2) Define a further set of tagged value types with the same Detail named "par1", "par2" and so on.

3) Define a profile with a Class stereotype "funptr" containing a "retval" tagged value (but no "par" tags).

4) Modify the code generation scripts Attribute Declaration and Parameter to retrieve the "retval" (always) and "par1" - "parN" (where defined) and generate correct syntax for them. This will be the tricky bit and I haven't actually done this. I think it can be done without too much effort, but you'll have to try it. You should also make sure that no code is generated for "funptr" class definitions as they represent anonymous types, not typedefs.

5) In your target project, define a set of classes to represent the primitive C types.

With this, you can define a function pointer type as a «funptr» class with a name like "long(*)(char)" for a function that takes a char and returns a long.

In the "retval" tag, select the "long" class you defined in step 4.

Add the "par1" tag manually, and select the "char" class as above.

You can now use this class as the type of an attribute or parameter, or anywhere else where EA allows a class reference (such as in the "par1" tag of a different «funptr» class; this allows you to easily create pointer types for functions where one of the parameters is itself of a function pointer type).

The hackiest bit here is the numbered "par1" - "parN" tags. While it is possible in EA to define several tags with the same name (you may have to change the tagged value window options to see them), I don't think you could retrieve the different values in the code generation script (and even if you could I don't think the order would necessarily be preserved, and parameter order is important in C). So you'd need to decide the maximum number of parameters beforehand. Not a huge problem in practice; setting up say 20 parameters should be plenty.

This method is of no help for reverse engineering, as EA 9 does not allow you to customize the reverse-engineering process. However, the upcoming EA 10 (currently in RC 1) will allow this, although I haven't looked at it myself so I don't know what form this will take.

这篇关于C / C ++函数指针的UML表示的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆