Представление UML для указателей функций C/С++ - программирование
Подтвердить что ты не робот

Представление UML для указателей функций C/С++

Каким будет лучшее представление указателя функции C/С++ (fp) в структурной диаграмме UML?

Я думаю об использовании элемента интерфейса, может быть даже, если "вырожден" с ограничением наличия не более одной объявленной операции.

Я нашел некоторое предложение в этом документе: Руководство по синхронизации C и UML, раздел 5.7.4. Но это звучит довольно громоздко и не очень полезно на практике. Даже если правильно с очень низкого уровня семантического зрения. Вот схема, кратко иллюстрирующая их концепцию: enter image description here

IMHO в указателях функций C и С++ используется как суженный вид интерфейса, который предоставляет только одну функцию и ее подпись. В C fp будет использоваться также для реализации более сложных интерфейсов, объявляющих структуру, содержащую набор указателей функций.

Я думаю, что мне даже удастся заставить мой конкретный инструмент UML (Enterprise Architect) переслать код сгенерированного кода и синхронизацию с изменениями кода без вреда.

Мои вопросы:

  • Будет ли объявление fp как части элементов интерфейса в UML proivde правильным семантическим представлением?
  • Какой стереотип следует использовать для объявления одного fp? По крайней мере, мне нужно предоставить typedef в коде , поэтому это будет мой выбор кистей. (я нашел этот стереотип запатентован для Enterprise Architect), и мне нужно определить подходящий стереотип, чтобы получить адаптацию кода, На самом деле я выбрал имя "идентификатор" стереотипа, имеет ли это какие-либо последствия или семантические столкновения?
  • Что касается С++, было бы вложение в стерилизованный интерфейс делегата с элементом класса достаточно, чтобы правильно выразить указатель на функцию члена класса?

Вот примерная диаграмма моих мыслей для представления языка C: C language interface and function pointer implementation

Это код C, который должен быть сгенерирован из приведенной выше модели:

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:
Вся проблема сводится к тому, что было бы наилучшим образом с помощью инструмента UML и его специфических возможностей разработки кода. Таким образом, я добавил enterprise-architect.

4b9b3361

Ответ 1

В файле справки EA есть указание на предмет указателей функций:

При импорте исходного кода на С++ Enterprise Architect игнорирует объявления указателей функций. Чтобы импортировать их в вашу модель, вы можете создать typedef для определения типа указателя функции, а затем объявить указатели на функции, используя этот тип. Указатели функций, объявленные таким образом, импортируются как атрибуты типа указателя функции.

Примечание "может". Это из раздела С++, в разделе C не упоминаются указатели на функции. Таким образом, они не очень хорошо поддерживаются, что, в свою очередь, конечно, связано с разрывом между сообществами моделирования и программирования: нетривиальные языковые концепции просто не поддерживаются в UML, поэтому любое решение по необходимости должно быть специфичным для конкретного инструмента.

Мое предложение немного связано и немного взломанно, но я думаю, что он должен работать очень хорошо.

Поскольку в UML-операциях не являются первоклассными и не могут использоваться как типы данных, мой ответ заключается в создании для них первообразных объектов, другими словами, определения типов указателей функций в качестве классов.

Эти классы будут служить двум целям: имя класса будет отражать подпись типа функции, чтобы он выглядел знакомым программисту на диаграммах, тогда как набор отмеченных значений будет представлять фактические параметры и типы возврата для использования в генерации кода.

0) Вы можете настроить технологию MDG для шагов 1-4.

1) Определите тегированный тип значения "retval" с помощью параметра Detail "Type = RefGUID; Values ​​= Class;"

2) Определите еще один набор методных типов значений с той же деталью, что и "par1", "par2" и т.д.

3) Определите профиль с помощью стереотипа класса "funptr", содержащего отмеченное тегом "retval" (но не теги "par" ).

4) Измените сценарии генерации кода Атрибут атрибута и Параметр, чтобы получить "retval" (всегда) и "par1" - "parN" (где определено) и создать для них правильный синтаксис. Это будет сложный бит, и я на самом деле этого не сделал. Я думаю, что это можно сделать без особых усилий, но вам придется попробовать. Вы также должны убедиться, что для определений классов "funptr" не генерируется код, поскольку они представляют собой анонимные типы, а не typedefs.

5) В вашем целевом проекте определите набор классов для представления примитивных типов C.

С помощью этого вы можете определить тип указателя функции как класс "funptr" с именем "long (*) (char)" для функции, которая принимает char и возвращает длинный.

В теге "retval" выберите "длинный" класс, который вы определили на шаге 4.

Добавьте тег "par1" вручную и выберите класс "char", как указано выше.

Теперь вы можете использовать этот класс как тип атрибута или параметра или где-либо еще, где EA позволяет использовать ссылку на класс (например, в теге par1 другого класса "funptr", что позволяет легко создавать типы указателей для функций, где один из параметров сам по себе является типом указателя функции).

Самый взломанный бит - это пронумерованные теги "par1" - "parN". Хотя в EA можно определить несколько тегов с тем же именем (возможно, вам придется изменить параметры окна с тегами значений, чтобы увидеть их), я не думаю, что вы могли бы получить разные значения в генерации кода script (и даже если бы вы могли не думать, что порядок обязательно будет сохранен, а порядок параметров важен в C). Поэтому вам нужно будет решить максимальное количество параметров заранее. На практике это не проблема. настройка говорит, что 20 параметров должны быть достаточными.

Этот метод не поможет в обратном проектировании, поскольку EA 9 не позволяет настроить процесс обратного проектирования. Тем не менее, предстоящий EA 10 (в настоящее время в RC 1) позволит это, хотя я сам не смотрел на него, поэтому не знаю, какую форму это займет.

enter image description here

Ответ 2

Определение указателей функций выходит за рамки спецификации UML. Более того, это специфичная для языка функция, которая не поддерживается многими программами моделирования UML. Поэтому я думаю, что общий ответ на ваш первый вопрос предполагает избегать этой функции. Представленные вами трюки имеют отношение только к Enterprise Architect и не совместимы с другими инструментами моделирования UML. Вот как указатели на функции поддерживаются в другом программном обеспечении UML:

MagicDraw. UML использует < < C++FunctionPtr → > стереотипы для членов класса FP и < C++FunctionSignature → для прототипа функции.

Пример кода (взятый из официальный сайт - см. "Моделирование typedef и указатель функции для создания кода на С++" ):

class Pointer
{
    void (f*) ( int i );
}

Соответствующая модель UML:

Function pointers in MagicDraw UML

Objecteering определяет атрибуты FP с соответствующей записью С++ TypeExpr.

Rational Software Architect от IBM не поддерживает указатели на функции. Пользователь может добавить их к сгенерированному коду в пользовательских разделах, которые остаются нетронутыми во время преобразования кода и UML и UML- > .

Ответ 3

Кажется правильным для меня. Я не уверен, что вы должны погрузиться в низкоуровневые детали описания типа и отношения вашего единственного указателя на функцию. Обычно я нахожу, что для описания интерфейса достаточно детализации без необходимости разлагать внутренние элементы.

Ответ 4

Я думаю, вы могли бы фактически обернуть указатель на функцию классом. Я думаю, что UML не должен быть стандартным для кода, документирование концепции более важно.

Ответ 5

Я чувствую, что вы хотите сопоставить UML-интерфейсы с идиомой struct-with-function-pointers.

Интерфейс1 является важным элементом вашей модели. Объявление типов объектов указателя функции по всему месту сделает ваши диаграммы неразборчивыми.

Enterprise Architect позволяет указать собственные генераторы кода. Найдите шаблонную структуру шаблонов. Вы должны иметь возможность модифицировать существующий генератор кода для C с помощью нового стереотипа или двух.

Ответ 6

Как и ваш первый пример, я бы использовал классификатор, но скрывал его в профиле. Я думаю, что они включили его для ясности объяснения концепции; но на практике вся идея стереотипов абстрагируется от деталей в профилях, чтобы избежать проблемы "шума". EA подходит для обработки профилей.

В отличие от первого примера, я бы классифицировал стереотип примитивного типа, а не Тип данных. Тип данных - это объект области видимости домена, а примитивный тип - это атомный элемент с семантикой, определяющий сторону области UML. Это не значит, что вы не можете добавлять заметки, особенно в профиль, или дать ему очень четкое имя стереотипа, например functionPointer.

Ответ 7

Мне удалось получить что-то вроде работы с Enterprise Architect. Это немного хакерское решение, но оно отвечает моим потребностям. Что я сделал:

  • Создайте новый стереотип класса с именем FuncPtr. Я последовал за гидом здесь: http://www.sparxsystems.com/enterprise_architect_user_guide/10/extending_uml_models/addingelementsandmetaclass.html Когда я это сделал, я сделал новое представление для профиля. Поэтому я могу держать его в стороне от моего основного проекта.

  • Изменены шаблоны кода класса. В основном выберите язык C и начните с шаблона класса и нажмите "Добавить новое переопределение стереотипа" и добавьте FuncPtr в качестве нового переопределения.

  • Добавьте следующий код к этому новому шаблону:

%PI="\n"%
%ClassNotes%
typedef %classTag:"returnType"% (*%className%)(
%list="Attribute" @separator=",\n" @indent="    "%
);
  1. Изменен шаблон кода декларации атрибута. Как и раньше, добавление нового стереотипа

  2. Добавьте в новый шаблон следующий код:

% PI = "%% attConst ==" T "?" const ":" "%

% attType%

% attContainment ==" По ссылке "?" * ":" "%

% AttName%

Это все, что я должен был сделать, чтобы получить указатели на функции в Enterprise Architect. Когда я хочу определить указатель на функцию, я просто:

  • Создать обычный класс
  • Добавьте в тег 'returnType' с типом возврата, который я хочу
  • Добавить атрибуты для параметров.

Таким образом, он создаст новый тип, который может быть включен как атрибуты или параметры в другие классы (структуры) и операторы. Я не сделал это сам оператор, потому что тогда он не был бы указан внутри инструмента как тип, который вы можете выбрать.

Итак, он немного взломан, используя специальные стереотипные классы как typedefs для указания указателей.