Как перевести код с c на python
Перейти к содержимому

Как перевести код с c на python

Портируем код C/C++ на Python

В первой части нашего небольшого цикла статей мы исследовали возможность использования структур данных в Python, которые были созданы с помощью языков программирования C/C++. Для этого мы рассмотрели библиотеку Ctypes.

В этой статье попробуем разобраться, какие еще есть подходы для работы с языками С/С++ и их аналогами, и также рассмотрим возможность анализа С/С++ исходников языков программирования и их компиляции налету. К тому же ответим на вопрос, а можно ли сделать интеграцию C/C++ в языке программирования Python прямо в скрипте. Подобный подход очень размоет границы между языками программирования, но это очень интересный функционал, который возможно может быть полезным.

Библиотека CFFI

Библиотека для работы с С из языка программирования Python. Написана с использованием pycparser, то есть это полноценный парсер языка программирования C и еще несколько дополнительных функций. Как это работает? Библиотека позволяет определять прототипы функций и производить их компиляцию. После проведения этих операций из Python можно вызывать функцию C, как будто она была определена изначально на Python.

Чтобы можно было использовать библиотеку, достаточно ввести вот такую команду:

pip install cffi

Для примера того, как можно работать с этой библиотекой, проведем уже известный из предыдущей статьи эксперимент. Попробуем вызвать MessageBoxA из системной библиотеки. Вот так будет выглядеть код:

Результат выполнения скрипта будет таким:

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

Все работает так же, как если бы мы просто создавали кусочки быстрого и эффективного кода на С. А что же насчет С++? К сожалению, эта библиотека не умеет работать с С++, но есть достойный аналог — cppyy.

cppyy

Библиотека для автоматической компиляции и работы с С++ из Python и наоборот. Компиляция и работа с кодом осуществляется в рантайме, поэтому конструкции языка С++ можно определять так же, как это было для С в cffi.
Cppyy построена поверх интерпретатора cling. Cling умеет работать с C++ благодаря тому, что использует clang и LLVM. По факту, это является способом быстрой разработки и прототипирования для С++.

Библиотека устанавливается достаточно просто:

pip install cppyy

Так как для работы библиотеке нужен так называемый backend, то при установке будут собираться расширения для её работы. Поэтому стоит установить Build Tools для сборки С++ приложений от MS. После установки всего необходимого нужно разобраться с принципом работы библиотеки.

Разработчики уверяют, что библиотеку можно использовать для всех конструкций языка. Однако стоит иметь в виду некоторые особенности. Библиотека для своей работы определяет объекты, которые в Python будут использоваться для корректной работы языка С++:

cppyy определяет один общий namespace — cppyy.gbl. Именно здесь можно будет найти объекты, которые мы будем создавать для тестирования функций языка С++.

Если требуется создать новый namespace, он будет присоединяться к глобальному — cppyy.gbl.newSpace.

Для адаптации конструкций под синтаксис Python можно описывать переменные из класса с помощью lambda выражений.

Кусочки или целый алгоритм можно определять через функцию cppyy.cppdef.

Рассмотрим простой пример класса с конструктором. Этот класс будет на этапе создания объекта присваивать значения для переменной внутри класса. Для знакомства с библиотекой лучше использовать интерактивный шелл от Python, подойдет и IDLE. Ниже кусочки кода, которые можно вводить и изучать работу cppyy. Такой подход используется не случайно, потому чтобы работать с любым объектом из cppyy, нужно каждый раз запускать процедуру отправки данных в cling, что требует времени. Поэтому мы сначала определяем класс или namespace и потом их нужно импортировать в Python для использования.

Можно также работать со стандартными типами и библиотеками, например, создать вектор и инициализировать его уже в Python:

Все обращения к созданному вектору будут контролироваться через Python, но, если необходимо, также работать с низкоуровневым представлением памяти и объектов, то есть отдельный набор функций cppyy.ll. Ниже пример, как можно выделить кусок сырых данных через malloc.

И крайний пример, как можно определить виртуальную функцию класса на С++:

Вот такие интересные проекты существуют для стирания границ между языками программирования. Благодаря чему это возможно? Библиотеки, расмотренные в этой статье, по сути просто обертки вокруг функций LLVM и clang. О чем эти технологии и как ими можно пользоваться из Python, разберемся в следующей статье.

Читать еще:

Также приглашаю всех желающих на бесплатный демоурок в рамках которого обсудим различные виды типизации, заглянем в теорию типов, рассмотрим примеры и best practice по аннотированию в Python, а также поговорим про существующие type checker’ы. Регистрация уже доступна по ссылке.

Перевести алгоритмический C на Python

Я хотел бы перевести код C в код Python или байт-код. Рассматриваемый код C — это то, что я бы назвал чисто алгоритмическим: независимость от платформы, без ввода-вывода, только алгоритмы и структуры данных в памяти.

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

Какие конкретные подходы, инструменты и техники вы можете порекомендовать?

Примечание. Расширение Python C или ctypes — не вариант, потому что среда изолирована.

Другое примечание: похоже, есть Компилятор байт-кода C в Java, они даже скомпилировали libjpeg на Java. Байт-код Java + ВМ слишком отличается от байт-кода + ВМ CPython?

Формы c голосовым вводом в React с помощью Speechly

Flatpickr: простой модуль календаря для вашего приложения на React

Что такое cURL в PHP? Встроенные функции и пример GET запроса

Ответы 9

Почему бы не сохранить код C и создание модуля Python C, которые можно импортировать в работающую среду Python?

Расширение Python C не подходит, потому что среда изолирована. Я обновил вопрос, чтобы отразить это.

Во-первых, я бы подумал о том, чтобы обернуть существующую библиотеку C добротой Pythonic, чтобы предоставить API в виде модуля python. Я бы посмотрел на swig, ctypes, pyrex и все остальное, что есть сейчас. Сама библиотека C останется там без изменений. Сохраняет работу.

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

Я упомянул Pyrex — это язык, похожий на C, но также ориентированный на Python. Я мало что сделал с этим, но это может быть проще, чем писать чистый питон, учитывая, что вы начинаете с C в качестве руководства.

Преобразование с более ограниченных, более укрощенных языков, таких как IDL (языки данных, которые любят использовать ученые, а не другие IDL), сложно и требует ручных и умственных усилий. C? Забудьте об этом до тех пор, пока люди с НЛО не предоставят нам свои модные программные инструменты, которые на тысячу лет опережают наши достижения!

«Макромагия» не является принципиальной проблемой, она устраняется одним проходом препроцессора.

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

Намного, намного лучший подход в целом действительно состоит в том, чтобы сохранить C как C и обернуть его в модуль расширения Python (используя SWIG, Pyrex, Cython или написать обертку вручную) или вызвать библиотеку C напрямую, используя ctypes. Все преимущества (и недостатки) C для того, что уже C или вы добавляете позже, и все удобства (и недостатки) Python для любого кода на Python.

Это не удовлетворит ваши потребности в «песочнице», но вы должны понимать, что в любом случае вы не сможете использовать Python в песочнице особенно хорошо; это требует больших усилий и модификации CPython, и если вы забудете одну маленькую дырочку где-то, ваша тюрьма сломается. Если вы хотите изолировать Python в песочнице, вы должны начать с изолирования всего процесса, а затем расширения C также могут быть изолированы.

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

Самый быстрый способ (с точки зрения усилий программиста, а не эффективности), вероятно, будет включать использование существующего компилятора для компиляции C в нечто простое (например, LLVM) и либо:

  • интерпретировать это в Python (непомерное снижение производительности)
  • переведите это на Python (огромная потеря производительности)
  • перевести это в байт-код Python (большая потеря производительности)

Возможен прямой перевод C на Python (и, вероятно, он дает более быстрый код, чем вышеприведенные подходы), но вы, по сути, напишете бэкэнд компилятора C, что является огромной задачей.

Изменить, запоздалое: возможно, еще более быстрый и грязный способ сделать это — взять дерево синтаксического анализа для кода C, преобразовать его в структуру данных Python и интерпретировать его в Python.

Я думал о LLVM, но не думал о его интерпретации. Хорошая точка зрения.

Что ж, может быть проще интерпретировать дерево синтаксического анализа C непосредственно в Python — добавлено это в правке.

andreikop/cpp2python

The script helps to convert C/C++ sources to C/C++ -like Python sources.

It does some simple edit operations like removing semicolons and type declarations. After it you must edit code manually, but you’ll probably spend less time doing it.

The utility will make mistakes and will not generate ready for use code, therefore it won’t be useful for you unless you know both C/C++ and Python.

For better result, it is recommended to format your code to ANSI style before performing conversion.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *