Рабочий процесс преобразования С++ в C

Во-первых, я не ищу инструмент, который будет создавать недопустимый код C из существующей базы кода cpp. Это требование от клиента, поэтому я не могу просто использовать базу кода CPP.

Я пытаюсь разработать рабочий поток, чтобы я мог конвертировать базу кода из CPP в C постепенно, не нарушая код. Я продумал несколько вещей, используя подход "extern C"

  • Классы для структур
  • Функции-члены классов будут преобразованы в формат Struct_name_FunctionName.
  • Если функция повторно используется 2-мя классами, я планирую использовать указатели на функции.
  • Замените перегруженные операторы, такие как +, - и т.д. с помощью реальных функций. Например, Add_, Sub_ и т.д.

Можете ли вы добавить больше? и указать на потенциальные ямы? Я не могу разделить кодовую базу из-за NDA. База кода сама по себе не огромна. Он получил около 50 файлов cpp, увидел около 100 нечетных классов.

Спасибо заранее.

P.s Я рассмотрел некоторые другие вопросы, которые звучат одинаково. Но у них действительно нет рабочего потока, который я ищу.

[Закрытие]: хотя сообщение было приостановлено, потому что оно слишком широкое, многие комментарии были действительно полезными. Я понимаю, что нужно сделать, чем раньше. Спасибо.

Ответ 1

Хорошо, там очень длинный список, который вам придется решать. Не претендуя на полноту, вам также необходимо:

  • Поддержка виртуальных функций (не трудно, таблица указателей функций)
  • Конструкторы и деструкторы (Разумное сопоставление с обычными функциями, много работы)
  • Исключения и разматывание пакетов (чрезвычайно сложно)
  • Отсутствие функций и классов библиотеки С++ (много работы)

Но не обманывай себя. std::map<std::string, std::pair<int, int>> - очень простой класс, который хранит по две строки для каждой строки. C-перевод этого класса - беспорядок. MyMap["five,three"] = std::make_pair(5,3) может легко стать 100 + строками кода C.

Ответ 2

Если ваш код на С++ широко использует конструкторы OO - особенно наследование и полиморфизм - вы можете посмотреть некоторые библиотеки C, которые имитируют это в C. qobject (из исходного дерева qemu) - это тот, который я хорошо знаю, но лучше (почти для всех меня), http://en.wikipedia.org/wiki/GObject, который исходит из glib. В настоящее время это не связано с графическим интерфейсом.

Преимущество в том, что вы можете изменить используемый язык, не внося слишком много изменений в поток программы.

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

Ответ 3

Следуя совету, чтобы взять GObject в качестве примера того, как С++-подобный код выполняется на C, можно попробовать одну вещь:

  • Перевести код С++ на Vala
  • Сгенерировать код C из компилятора Vala.

Вала - язык, похожий на С#; за исключением того, что вам нужно будет повторить "public" или "private" в каждой сигнатуре функции, а также избавиться от указателя-звезды в используемых классах, вам нечего делать.

Конечно, сгенерированный код C будет выглядеть таким же уродливым, как у других генераторов, но, по крайней мере, есть некоторые короткие способы, как сделать его "поддерживаемым" кодом (основная проблема заключается в том, что каждый объект, созданный в результатах Vala в инкрементном контрольном счетчике в C-коде, что не всегда необходимо).

Модель GObject может быть хорошей инструкцией/примером о том, как переводить конструкты С++ в то же самое в C. Если вы не используете исключения (Vala does!:)), с этим не должно быть никаких проблем. Конечно, основными рекомендациями являются:

  • Нормальные методы: используйте указатель на объект в качестве первого аргумента. Имя функции - NAMESPACE_CLASSNAME_METHODNAME.
  • Виртуальные методы: вам нужно создать "характерный объект", обозначенный "объектом" этого класса, который содержит указатели на функции. Объекты класса обычно создаются в GObject в функциях, которые возвращают указатель на этот объект - сам объект лениво создается и сохраняется в статической локальной переменной.
  • Перегрузка: добавление разделяющих имя частей (Vala не поддерживает перегрузку, даже в конструкторах - конструкторы используют специальный синтаксис для вызова именованных конструкторов)
  • Шаблоны: развернуть на месте:)
  • Вывод: только один вывод (как и в Vala), делает первое поле структуры "производного класса" полем типа структуры "базового класса".
  • Вызов методов из базовых классов: используйте C cast. Если вы следуете точке 5, вы должны просто наложить структуру объекта производного класса на структуру базового класса.