Skip to content
C parser and interpreter written in Python with automatic ctypes interface generation
Python C
Branch: master
Clone or download
Latest commit 080a7b0 Oct 5, 2019
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
demos use relative imports Oct 3, 2019
screenshots demo Sep 14, 2019
sortedcontainers added sorted_containers 1.4.4 Dec 21, 2015
tests fix struct unnamed var Oct 4, 2019
.gitignore gitignore Sep 12, 2019
LICENSE Create LICENSE Sep 14, 2019
README.md demo Sep 14, 2019
__init__.py use relative imports Oct 3, 2019
caching.py Fix indent May 27, 2018
cparser.py wint_t Oct 4, 2019
cparser_utils.py Python 3 fixes, mostly ast Sep 13, 2019
cwrapper.py use relative imports Oct 3, 2019
globalincludewrappers.py handle wchar.h Oct 4, 2019
goto.py
interpreter.py enum parsing, small fix Oct 4, 2019
interpreter_utils.py Python 3 fixes, mostly ast Sep 13, 2019
py_demo_unparse.py use relative imports Oct 3, 2019
requirements.txt requirements Sep 14, 2019
runcprog.py replace itertools takewhile/dropwhile search for "--" with list.index Aug 9, 2018

README.md

PyCParser

https://github.com/albertz/PyCParser

A C parser and interpreter written in Python. Also includes an automatic ctypes interface generator.

It is looser than the C grammar, i.e. it should support a superset of the C language in general.

Some of the support may a bit incomplete or wrong at this point because I didn't really strictly followed the language specs but rather improved the parser by iteration on real-world source code.

Similar projects

Parsers / ctypes interface generators:

  • Eli Bendersky's pycparser. Complete C99 parser in pure Python. It depends on Python Lex-Yacc (PLY). (I didn't tested it yet. Seems to be the most complete and most professional project. If you don't want a C interpreter, this is probably the project you should use.)
  • pyclibrary (Github fork). Is quite slow and didn't worked that well for me.
  • ctypesgen. Also uses Lex+Yacc.
  • codegen. Uses GCC-XML. See below about the disadvantages of such an aproach.

Interpreters:

  • CInterpreter. Python.
  • CINT. Not in Python. Probably the most famous one.
  • Ch. Not in Python. Is not really free.
  • ups debugger. Not in Python.
  • PicoC. Not in Python. "A very small C interpreter."
  • BIC. Not in Python.

Why this project?

  • Be more flexible. It is much easier now with a hand-written parser to do operations on certain levels of the parsing pipe.
  • I wanted to have some self-contained code which can also easily run on the end-user side. So the end-user can just update the lib and its headers and then some application using this Python lib will automatically use the updated lib. This is not possible if you generated the ctypes interface statically (via some GCC-XML based tool or so).
  • I wanted to implement PySDL and didn't wanted to translate the SDL headers by hand. Also, I didn't wanted to use existing tools to do this to avoid further maintaining work at some later time. See the project for further info.
  • This functionality could be used similarly for many other C libraries.
  • A challenge for myself. Just for fun. :)

Examples

  • PySDL. Also uses the automatic ctypes wrapper and maps it to a Python module.
  • PyCPython. Interpret CPython in Python.
  • PyLua. Interpret Lua in Python.

Also see the tests/test_interpreter.{c,py} 'Hello world' example.

Also try out ./demos/interactive_interpreter.py --debug.

Current state

  • Many simple C programs should be parsed and interpret correctly now.
  • I'm quite sure that function pointer typedefs are handled incorrectly. E.g. typedef void f(); and typedef void (*f)(); are just the same right now. See cpre3_parse_typedef and do some testing if you want to fix this.
  • Many functions from the standard C library are still missing.
  • There might be some bugs. :)
  • C++ isn't supported yet. :)
  • The code style does not conform to PEP8 and standard Python conventions in many places, as it is quite old. Also, it probably should be restructured, as it has grown too much in single files. I'm slowly fixing this.

How does the interpreter work

This is probably a bit unusual. We wrap the most important standard C library functions directly to the native libc, via ctypes. We translate the parsed C code to a equivalent Python AST (via ast), which makes heavy use of ctypes. Then we just run this generated Python code. But we can also dump it. Thus we can compile C code to an equivalent Python program.

demo

--- Albert Zeyer, http://www.az2000.de

You can’t perform that action at this time.