Tiny C Compiler mit Python nutzen

Code-Stücke können hier veröffentlicht werden.
Antworten
jerch
User
Beiträge: 1669
Registriert: Mittwoch 4. März 2009, 14:19

Aus Spass an der Freude hab ich mal den Tiny C Compiler mit Python kombiniert. Getestet unter Linux (64Bit) und Windows7 (32Bit Version). Wusste gar nicht, dass der TCC inzwischen auch Assembler beherrscht. :)

Und noch der Code:

Code: Alles auswählen

import os
import sys
from ctypes import CDLL, c_void_p

DIR = os.path.dirname(os.path.abspath(__file__))

WINDOWS = False
LIBNAME = 'libtcc.so.1.0'
if sys.platform == 'win32':
    WINDOWS = True
    LIBNAME = 'libtcc.dll'

def tcc_compile(symbols,
                source,
                shared_library=os.path.join(DIR, LIBNAME),
                static_path=DIR):
    """
    arguments:
    `symbols`        - dictionary in the form of
                       {'c function name': ctypes.CFUNCTYPE()}
    `source`         - c source code
    `shared_library` - path to tcc shared lib as loaded by ctypes
                       (defaults to module path + libtcc.so.1.0)
    `static_path`    - path to folder of tcc static lib
                       (defaults to module path)
    """
    lib = CDLL(shared_library)
    lib.tcc_get_symbol.restype = c_void_p
    tccstate = lib.tcc_new()
    lib.tcc_set_lib_path(tccstate, static_path)
    lib.tcc_add_include_path(tccstate, static_path)
    lib.tcc_set_output_type(tccstate, 0)
    if WINDOWS:
        lib.tcc_add_file(tccstate, os.path.join(static_path, 'libtcc.def'))
    if lib.tcc_compile_string(tccstate, source) == -1:
        raise Exception('error in tcc compilation')
    if lib.tcc_relocate(tccstate, 1) == -1:
        raise Exception('error in tcc relocation')
    functions = {}
    for funcname, functype in symbols.items():
        funcpointer = lib.tcc_get_symbol(tccstate, funcname)
        if not funcpointer:
            raise Exception('c function "%s" not found' % funcname)
        functions[funcname] = functype(funcpointer)
    lib.tcc_delete(tccstate)
    return functions

if __name__ == '__main__':
    from ctypes import CFUNCTYPE, c_int

    code = '''
int func1() {
    return 42;
}
int func2(int a) {
    int res;
    asm("add $19,%%eax" : "=a" (res): "a" (a)); // with asm support
    return res;
}
'''
    functions = tcc_compile(
        {'func1': CFUNCTYPE(c_int), 'func2': CFUNCTYPE(c_int, c_int)},
        code)
    print functions['func1'](), functions['func2'](23)
TCC installieren:

Code: Alles auswählen

Linux
1) Download tcc source package (tested with tcc-0.9.26.tar.bz2)
2) Compile libraries
        ./configure
        make libtcc.so.1.0
        make libtcc1.a
3) Copy to module path:
        libtcc.so.1.0
        libtcc1.a

Windows
1) Download tcc binary package (tested with tcc-0.9.26-win32-bin.zip)
2) Copy to module path:
        libtcc.dll
        libtcc\libtcc.def
        lib\ (whole folder)
Zuletzt geändert von Anonymous am Montag 7. November 2016, 11:32, insgesamt 1-mal geändert.
Grund: Codeboxen repariert.
jerch
User
Beiträge: 1669
Registriert: Mittwoch 4. März 2009, 14:19

Hab die Sache mal etwas aufgehübscht --> https://github.com/jerch/python-tinycc

Wenn es nach Python 3 portiert ist, werde ich versuchen, ein fertiges PyPi Paket daraus zu schnüren, was automatisch den TCC kompiliert (bzw. unter Windows binär mit ausliefert).

Hab es übrigens auch mal mit Numpy getestet, hat allerdings bei den simplen Tests, die ich gemacht habe, eine etwas schlechtere Laufzeit (waren nur ein paar skalare Operationen mit slicing). Falls jmd. noch Ideen zur Interaktion mit Python hat - immer her damit.
Antworten