Генерация кода C ++ с Python - PullRequest
9 голосов
/ 03 июня 2010

Может кто-нибудь указать мне документацию о том, как писать скрипты на Python (или Perl или любом другом дружественном для Linux языке скриптов), которые генерируют код C ++ из XML или py-файлов из командной строки. Я хотел бы иметь возможность записать некоторые XML-файлы, а затем выполнить команду оболочки, которая читает эти файлы и генерирует .h файлы с полностью встроенными функциями, например, потоковые операторы, конструкторы и т. д.

Ответы [ 8 ]

11 голосов
/ 20 июля 2012

Если вы хотите сделать это просто с помощью стандартного Python, вы можете попробовать создать файлы шаблонов, использующие форматирование строк в стиле Python 3.Например, шаблон класса может выглядеть примерно так:

{className}::{className}()
{{
}}

{className}::~{className}()
{{
}}

{className}::{className}(const {className}& other)
{{
}}

{className}& {className}::operator=(const {className}& other)
{{
    return *this;
}}

Тогда ваш код Python очень прост:

d = {}
d['className'] = 'MyCPlusPlusClassName'
with open(yourTemplateFile, 'r') as ftemp:
    templateString = ftemp.read()
with open(generatedFile, 'w') as f:
    f.write(templateString.format(**d))

Конечно, вы можете добавить множество других полей рядом с 'classNameиспользуя тот же трюк.Если вам не нужны такие вещи, как условная генерация кода, вы можете получить много пользы от чего-то такого простого.

2 голосов
/ 03 июня 2010

Боюсь, вы не найдете уже встроенного решения, которое берет ваши конкретные файлы xml или python и преобразует их в нужный вывод "из коробки".

Вам придется самостоятельно выполнять синтаксический анализ, обработку данных и выводить их. Не все в одиночку, хотя; Вот несколько советов, касающихся разбора и вывода.

Python поставляется с 2 различными анализаторами XML ( SAX и DOM - прокрутите вниз, чтобы увидеть некоторые примеры). Вам придется использовать один из них для чтения исходных файлов.

Для более легкой генерации вывода вы можете использовать библиотеку шаблонов, такую ​​как StringTemplate , или просто сгенерировать код вручную, если он маленький.

1 голос
/ 01 сентября 2016

Исходя из собственного опыта, я могу порекомендовать Jinja2 (http://jinja.pocoo.org/docs/dev/). Несмотря на то, что основным целевым языком Jinja является HTML, он достаточно хорошо работает для C ++. И это не только мое мнение, см. https://www.chromium.org/developers/jinja :). Существует автономная версия (https://github.com/filwaitman/jinja2-standalone-compiler), которая может быть полезна, поскольку Jinja2 сам по себе является только API. Я использую автономную версию для своего проекта здесь https://github.com/TomSmartBishop/avl с настроенными параметрами среды так что открывающие и закрывающие теги Jinja2 больше соответствуют стилю C ++.

1 голос
/ 03 июня 2010

Несколько лет назад я работал над проектом по упрощению межпроцессного управления общей памятью для крупномасштабных систем моделирования. Мы использовали связанный подход, в котором расположение данных в разделяемой памяти было определено в файлах XML, а генератор кода, написанный на python, считывал XML и выкладывал набор заголовочных файлов, определяющих структуры и связанные функции / операторы / и т. Д., Чтобы соответствовать XML описание В то время я посмотрел на несколько шаблонизаторов и, к своему удивлению, обнаружил, что проще и очень просто сделать это «вручную».

Когда вы читаете XML, просто заполните набор структур данных, которые соответствуют вашему коду. Файловые объекты заголовка содержат классы, а классы содержат переменные (которые могут быть других типов классов). Дайте каждому объекту printSelf() метод, который перебирает его содержимое и вызывает printSelf() для каждого объекта, который он содержит.

Поначалу это кажется немного сложным, но как только вы начинаете, это довольно просто. Да, и один совет, который помогает сгенерированным кодом, добавить аргумент отступа к printSelf() и увеличить его на каждом уровне. Это облегчает чтение сгенерированного кода намного .

1 голос
/ 03 июня 2010

Посмотрите на Гепард . Это шаблонизатор, написанный на Python.

1 голос
/ 03 июня 2010

Вы можете взглянуть на Shedskin , проект, который генерирует код C ++ из кода Python.

В зависимости от ваших причин, это может быть немного бессмысленно, как указал Сатанипуппи.

0 голосов
/ 08 января 2018

Надеюсь, это кому-нибудь пригодится (вы можете использовать буфер обмена win32 для чтения данных)

import sys, string
import win32clipboard
import re


data = '''
     enum FeedTypeT
     {
         AA,
         BB,
         DDD,
         F
     };
'''

def get_from_clippord():
    # get clipboard data
    win32clipboard.OpenClipboard()
    data = win32clipboard.GetClipboardData()
    win32clipboard.CloseClipboard()
    return data

def enum_type(inenum):
    inenum = inenum.replace('\r\n', '\n')
    inenum = re.sub( r'\s', r'', inenum )
    inenum = re.sub( r'^(.*)\{.*$', r'\1', inenum )
    return inenum

def cleanup_enum(inenum):
    inenum = inenum.replace('\r\n', '\n')
    # inenum = inenum.replace('enum', '')
    inenum = re.sub( r'\s', r'', inenum )
    # inenum = re.sub( r'^.*\{(.+)[|,]\}.*$', r'\1', inenum )
    inenum = re.sub( r'^.*\{(.+)\}.*$', r'\1', inenum )
    inenum = inenum.split(',')
    return inenum

def get_element(inlist):
    for element in inlist:
       [one, two] = element.split('=')
       print('{0:20} ==> {1:>20}'.format(one, two))         # right align
#      one = element.split('=')
#      print('{0:20} ==> {1:10}'.format(one[0], one[1]))

def print_switch(typename):
    retstr = 'const std::string toString( ' + typename + ' type )'
    retstr += '\n{\n   switch( type )\n   {'
    return retstr

def print_case_line(instr, w):
    retstr = '      case ' + '{:{fw}}'.format(instr + ':', fw = w) + ' return "' + instr + '";'
    return retstr

def print_switch_end(w):
    retstr = '      default: ' + ' '*(w-4) + ' return "undef";\n   }\n}\n'
    return retstr

def main():
    #data = get_from_clippord()

    ll = cleanup_enum(data)
    print ( ll )
    print ("="*80 + "\n\n")
    print ( print_switch( enum_type(data)) )

    w = 25
    # pick right with for formating, based on the lenght of elements of enum
    for line in ll:
       if w < len(line):
          w = len(line) + 2

    for line in ll:
       print ( print_case_line(line, w) )

    print ( print_switch_end(w) )


if __name__ == '__main__':
    main()

Выход:

['AA', 'BB', 'DDD', 'F']
================================================================================


const std::string toString( enumFeedTypeT type )
{
   switch( type )
   {
      case AA:                       return "AA";
      case BB:                       return "BB";
      case DDD:                      return "DDD";
      case F:                        return "F";
      default:                       return "undef";
   }
}
0 голосов
/ 03 июня 2010

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

При этом, 4GL в значительной степени смирился с кучей пыли в истории. Проблема заключается в том, что когда вы генерируете код C на машине, вы теряете прирост производительности, который был бы вызван использованием C в первую очередь, а код крайне сложно поддерживать. Можно также написать программу на Python.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...