## node-tinycc Tiny C Compiler binding for nodejs. With this module it is possible to declare inline C code in nodejs and run it on the fly. This is possible due to the fascinating Tiny C Compiler originally made by Fabrice Bellard. **Requires**: module:node-gyp, module:@napi-ffi/ffi-napi, module:@napi-ffi/ref-napi **Note**: The module is still alpha, interfaces are still likely to change a lot. **Example** ```js const tcc = require('node-tinycc'); // create a code generator let gen = tcc.CodeGenerator(); // create a compile state let state = tcc.DefaultTcc(); // declare a C function let c_func = tcc.c_function( 'int', // return type 'add', // function name in C [['int', 'a'], ['int', 'b']], // parameters as [type, name] 'return a + b + js_func(a, b);' // actual code ); gen.addDeclaration(c_func); // add a JS function declaration to C let js_func = tcc.c_callable( 'int', // return type 'js_func', // function name in C ['int', 'int'], // parameter types (a, b) => {return a * b;} // function ); gen.addDeclaration(js_func); // compile code and relocate state.compile(gen.code()); state.relocate(); // resolve symbols between C and JS gen.bindState(state); // now the C stuff is usable console.log(c_func(23, 42)); // --> prints 1031 ``` * [node-tinycc](#module_node-tinycc) * [.Tcc](#module_node-tinycc.Tcc) * [new Tcc(tcclib)](#new_module_node-tinycc.Tcc_new) * [.setOptions(option)](#module_node-tinycc.Tcc+setOptions) * [.setLibPath(path)](#module_node-tinycc.Tcc+setLibPath) * [.defineSymbol(symbol, [value])](#module_node-tinycc.Tcc+defineSymbol) * [.undefineSymbol(symbol)](#module_node-tinycc.Tcc+undefineSymbol) * [.addIncludePath(path)](#module_node-tinycc.Tcc+addIncludePath) * [.addLibrary(library)](#module_node-tinycc.Tcc+addLibrary) * [.addLibraryPath(path)](#module_node-tinycc.Tcc+addLibraryPath) * [.addFile(path)](#module_node-tinycc.Tcc+addFile) * [.compile(code)](#module_node-tinycc.Tcc+compile) * [.relocate()](#module_node-tinycc.Tcc+relocate) * [.addSymbol(symbol, value)](#module_node-tinycc.Tcc+addSymbol) * [.getSymbol(symbol)](#module_node-tinycc.Tcc+getSymbol) ⇒ ref.refType \| null * [.resolveSymbol(symbol, type)](#module_node-tinycc.Tcc+resolveSymbol) ⇒ \* * [.setSymbol(symbol, value)](#module_node-tinycc.Tcc+setSymbol) * [.getFunction(symbol, restype, args)](#module_node-tinycc.Tcc+getFunction) ⇒ ffi.ForeignFunction * [.setFunction(symbol, cb)](#module_node-tinycc.Tcc+setFunction) * [.FuncSymbol](#module_node-tinycc.FuncSymbol) * [new FuncSymbol(restype, args, f)](#new_module_node-tinycc.FuncSymbol_new) * [.Declaration](#module_node-tinycc.Declaration) * [new Declaration(code, [forward], [symbols])](#new_module_node-tinycc.Declaration_new) * [.CodeGenerator](#module_node-tinycc.CodeGenerator) * [new CodeGenerator()](#new_module_node-tinycc.CodeGenerator_new) * [.loadBasicTypes()](#module_node-tinycc.CodeGenerator+loadBasicTypes) * [.code()](#module_node-tinycc.CodeGenerator+code) ⇒ string * [.codeWithLineNumbers()](#module_node-tinycc.CodeGenerator+codeWithLineNumbers) ⇒ string * [.addDeclaration(decl)](#module_node-tinycc.CodeGenerator+addDeclaration) * [.addTopDeclaration(decl)](#module_node-tinycc.CodeGenerator+addTopDeclaration) * [.bindState(state)](#module_node-tinycc.CodeGenerator+bindState) ⇒ Object * [.WCString(s)](#module_node-tinycc.WCString) ⇒ WCString * [.escapeWchar(s)](#module_node-tinycc.escapeWchar) ⇒ string * [.DefaultTcc()](#module_node-tinycc.DefaultTcc) ⇒ [Tcc](#module_node-tinycc.Tcc) * [.CFuncType(restype, args, [variadic])](#module_node-tinycc.CFuncType) ⇒ function * [.c_callable(restype, name, args, f)](#module_node-tinycc.c_callable) ⇒ Declaration * [.c_function(restype, name, args, code)](#module_node-tinycc.c_function) ⇒ func * [.c_struct(name, structType)](#module_node-tinycc.c_struct) ⇒ StructType ### tcc.Tcc The Tcc class provides low level access to the libtcc-API of the Tiny C Compiler (TCC). On Windows this class is constructed in Javascript with `ffi` from a precompiled libtcc.dll delivered with the module. On POSIX systems the class is a C++ class build in a native extension from the repository source. **Kind**: static class of [node-tinycc](#module_node-tinycc) **Note**: It is important to note that you must not mix different TCC states. Because TCC uses global states internally, any new state will leave the old one corrupted. The compiled result is not affected by this, therefore it is important to finish a state up to the compilation before using a new one. This is a major drawback of the TCC API. Because of the global internal states it is also not possible to cleanup a state properly (a Tcc() invocation will leak memory). While this works: ```js let state1 = Tcc(); ... state1.compile('...') && state1.relocate(); // finished with state1 let state2 = Tcc(); // state1 got corrupted but we are done with it anyways ... state2.compile('...') && state2.relocate(); // finished with state2 // use symbols from state1 & state2 ``` this will break: ```js let state1 = Tcc(); let state2 = Tcc(); // state1 got corrupted, state2 is working as expected ``` * [.Tcc](#module_node-tinycc.Tcc) * [new Tcc(tcclib)](#new_module_node-tinycc.Tcc_new) * [.setOptions(option)](#module_node-tinycc.Tcc+setOptions) * [.setLibPath(path)](#module_node-tinycc.Tcc+setLibPath) * [.defineSymbol(symbol, [value])](#module_node-tinycc.Tcc+defineSymbol) * [.undefineSymbol(symbol)](#module_node-tinycc.Tcc+undefineSymbol) * [.addIncludePath(path)](#module_node-tinycc.Tcc+addIncludePath) * [.addLibrary(library)](#module_node-tinycc.Tcc+addLibrary) * [.addLibraryPath(path)](#module_node-tinycc.Tcc+addLibraryPath) * [.addFile(path)](#module_node-tinycc.Tcc+addFile) * [.compile(code)](#module_node-tinycc.Tcc+compile) * [.relocate()](#module_node-tinycc.Tcc+relocate) * [.addSymbol(symbol, value)](#module_node-tinycc.Tcc+addSymbol) * [.getSymbol(symbol)](#module_node-tinycc.Tcc+getSymbol) ⇒ ref.refType \| null * [.resolveSymbol(symbol, type)](#module_node-tinycc.Tcc+resolveSymbol) ⇒ \* * [.setSymbol(symbol, value)](#module_node-tinycc.Tcc+setSymbol) * [.getFunction(symbol, restype, args)](#module_node-tinycc.Tcc+getFunction) ⇒ ffi.ForeignFunction * [.setFunction(symbol, cb)](#module_node-tinycc.Tcc+setFunction) #### new Tcc(tcclib) | Param | | --- | | tcclib | #### state.setOptions(option) Set command line options of TCC. Run `tcc -hh` to see known options. **Kind**: instance method of [Tcc](#module_node-tinycc.Tcc) | Param | Type | | --- | --- | | option | string | #### state.setLibPath(path) Set TCC library path. For `DefaultTcc` this is set to the bundled TCC. **Kind**: instance method of [Tcc](#module_node-tinycc.Tcc) | Param | Type | | --- | --- | | path | string | #### state.defineSymbol(symbol, [value]) Define a preprocessor symbol. **Kind**: instance method of [Tcc](#module_node-tinycc.Tcc) | Param | Type | | --- | --- | | symbol | string | | [value] | string | #### state.undefineSymbol(symbol) Undefine a preprocessor symbol. **Kind**: instance method of [Tcc](#module_node-tinycc.Tcc) | Param | Type | | --- | --- | | symbol | string | #### state.addIncludePath(path) Add include path. **Kind**: instance method of [Tcc](#module_node-tinycc.Tcc) | Param | Type | | --- | --- | | path | string | #### state.addLibrary(library) Add a library (same name as -l...). **Kind**: instance method of [Tcc](#module_node-tinycc.Tcc) | Param | Type | | --- | --- | | library | string | #### state.addLibraryPath(path) Add a library path. Equivalent to -Lpath option. **Kind**: instance method of [Tcc](#module_node-tinycc.Tcc) | Param | Type | | --- | --- | | path | string | #### state.addFile(path) Add a file to compilation. **Kind**: instance method of [Tcc](#module_node-tinycc.Tcc) **Fixme**: missing filetype parameter | Param | Type | | --- | --- | | path | string | #### state.compile(code) Compile source code. **Kind**: instance method of [Tcc](#module_node-tinycc.Tcc) | Param | Type | | --- | --- | | code | string | #### state.relocate() Relocate after compilation. This is needed before resolving any symbols. **Kind**: instance method of [Tcc](#module_node-tinycc.Tcc) #### state.addSymbol(symbol, value) Add a symbol to the compiled program. This is not reliable on all architectures (likely to segfault on ARM). Use with caution. **Kind**: instance method of [Tcc](#module_node-tinycc.Tcc) | Param | Type | | --- | --- | | symbol | string | | value | ref.refType | #### state.getSymbol(symbol) ⇒ ref.refType \| null Get a symbol from the program. Returns void pointer or `null` of not found. **Kind**: instance method of [Tcc](#module_node-tinycc.Tcc) | Param | Type | | --- | --- | | symbol | string | #### state.resolveSymbol(symbol, type) ⇒ \* Resolve a C symbol name as type for further usage in Javascript. **Kind**: instance method of [Tcc](#module_node-tinycc.Tcc) **Note**: This is done automatically for known symbols in `CodeGenerator.bindState`. | Param | Type | Description | | --- | --- | --- | | symbol | string | symbol name | | type | string \| object | known type of `ref.types` | #### state.setSymbol(symbol, value) Low level function to set the value of a C symbol. Since all toplevel symbols are exported as void pointers, the value must be a pointer type. The referenced type of value has to match the C type of the symbol, otherwise arbitrary memory will be overwritten. **Kind**: instance method of [Tcc](#module_node-tinycc.Tcc) | Param | Type | Description | | --- | --- | --- | | symbol | string | symbol name | | value | ref.refType | | #### state.getFunction(symbol, restype, args) ⇒ ffi.ForeignFunction Resolve a C symbol name as function type. **Kind**: instance method of [Tcc](#module_node-tinycc.Tcc) | Param | Type | Description | | --- | --- | --- | | symbol | string | symbol name | | restype | string \| object | known type of `ref.types` | | args | array | array of parameter types | #### state.setFunction(symbol, cb) Set a C function pointer symbol to a Javascript callback. The callback must be a `ffi.Callback` matching the function pointer type. **Kind**: instance method of [Tcc](#module_node-tinycc.Tcc) | Param | Type | Description | | --- | --- | --- | | symbol | string | symbol name | | cb | ffi.Callback | Javascript callback | ### tcc.FuncSymbol **Kind**: static class of [node-tinycc](#module_node-tinycc) #### new FuncSymbol(restype, args, f) Internal wrapper for ffi.Callback to distingish a function type in `CodeGenerator.bindState`. It also holds a reference of the callback to avoid early garbage collection. | Param | Type | Description | | --- | --- | --- | | restype | string \| object | known type of `ref.types` | | args | Array | array of parameter types | | f | function | callback function | ### tcc.Declaration **Kind**: static class of [node-tinycc](#module_node-tinycc) #### new Declaration(code, [forward], [symbols]) Base object for all declarations to be used with CodeGenerator. If the standard convenient functions do not suit your needs you can create a customized declaration with this base object and still use the code generator. Add the returned declaration to a generator with `addDeclaration`. After the symbols got mapped by `CodeGenerator.bindState` you can access them via the attribute `.symbols_resolved`. | Param | Type | Description | | --- | --- | --- | | code | string \| function | C source as string or a function returning the source code string | | [forward] | string | optional forward declaration | | [symbols] | Array | optional array of [type, symbol name] to be autoresolved by the generator | **Example** ```js let declaration = new tcc.Declaration( ` // code int x = 1; int func_a() { return func_b() + 1; } int func_b() { return 0; } `, ` // forward int func_a(); int func_b(); `, [ // symbols ['int', 'x'], [tcc.CFuncType('int', []), 'func_a'], [tcc.CFuncType('int', []), 'func_b'] ]); ``` ### tcc.CodeGenerator **Kind**: static class of [node-tinycc](#module_node-tinycc) * [.CodeGenerator](#module_node-tinycc.CodeGenerator) * [new CodeGenerator()](#new_module_node-tinycc.CodeGenerator_new) * [.loadBasicTypes()](#module_node-tinycc.CodeGenerator+loadBasicTypes) * [.code()](#module_node-tinycc.CodeGenerator+code) ⇒ string * [.codeWithLineNumbers()](#module_node-tinycc.CodeGenerator+codeWithLineNumbers) ⇒ string * [.addDeclaration(decl)](#module_node-tinycc.CodeGenerator+addDeclaration) * [.addTopDeclaration(decl)](#module_node-tinycc.CodeGenerator+addTopDeclaration) * [.bindState(state)](#module_node-tinycc.CodeGenerator+bindState) ⇒ Object #### new CodeGenerator() Code generator for inline C in Javascript. The code generator creates the final source code by putting together single declarations. The structure of the final source code is the following: - top section: The section gets not autofilled by the generator. Use it with `addTopDeclaration` for any early stuff like including header files and such. - forward section: Used by the generator to do forward declarations. Any content in `Declaration.forward` will end up here. - code section: Used by the generator to place the code definitions. To add content to the sections call `addDeclaration` or `addTopDeclaration` for the top section. The order of added content is preserved, this is esp. important of you omit forward declarations. Example usage: ```js let gen = tcc.CodeGenerator(); gen.addTopDeclaration( tcc.Declaration('#include #### gen.loadBasicTypes() Add declarations for the common types of `ref.types`. Some of the known types of the ref module differ from typical C naming (e.g. `int8` instead of `int8_t`). This function adds additional typedefs to solve naming issues. It adds the following types: | Type | Typedef of | |-----------|--------------------| | int8 | int8_t | | int16 | int16_t | | int32 | int32_t | | int64 | int64_t | | uint8 | uint8_t | | uint16 | uint16_t | | uint32 | uint32_t | | uint64 | uint64_t | | Object | void * | | CString | char * | | byte | unsigned char | | uchar | unsigned char | | ushort | unsigned short | | uint | unsigned int | | ulong | unsigned long | | longlong | long long | | ulonglong | unsigned long long | Furthermore it includes ``, `` and ``. If the module `ref-wchar-napi` is installed, `WCString` is typedef'd as `wchar_t` pointer. **Kind**: instance method of [CodeGenerator](#module_node-tinycc.CodeGenerator) #### gen.code() ⇒ string Get the generated code. **Kind**: instance method of [CodeGenerator](#module_node-tinycc.CodeGenerator) #### gen.codeWithLineNumbers() ⇒ string Get the generated code with leading line numbers. This is useful for limited debugging. **Kind**: instance method of [CodeGenerator](#module_node-tinycc.CodeGenerator) #### gen.addDeclaration(decl) Add a declaration to the generator. **Kind**: instance method of [CodeGenerator](#module_node-tinycc.CodeGenerator) | Param | Type | Description | | --- | --- | --- | | decl | Declaration | declaration to be added | #### gen.addTopDeclaration(decl) Add a declaration to the top section. `forward` and `symbols` will be ignored for declarations added to the top section. **Kind**: instance method of [CodeGenerator](#module_node-tinycc.CodeGenerator) | Param | Type | Description | | --- | --- | --- | | decl | Declaration | declaration to be added | #### gen.bindState(state) ⇒ Object Resolve symbols between C and Javascript. Call this after compilation and relocation before using any C stuff. The function traverses all symbol names of the added declarations and tries to attach the given type. Returns an object with all symbol names mapping to the corresponding type. **Kind**: instance method of [CodeGenerator](#module_node-tinycc.CodeGenerator) | Param | Type | Description | | --- | --- | --- | | state | Tcc | state to bind to symbols | ### tcc.WCString(s) ⇒ WCString Helper function for easy wide string creation. **Kind**: static method of [node-tinycc](#module_node-tinycc) **Note**: The function is only exported, if the module `ref-wchar-napi` is installed. | Param | Type | | --- | --- | | s | string | ### tcc.escapeWchar(s) ⇒ string Helper function to escape wide character string literals. This is useful when writing C source code strings directly in Javascript. The function escapes the UTF-8 input to the appropriate wchar_t type. **Kind**: static method of [node-tinycc](#module_node-tinycc) **Note**: The function is only exported, if the module `ref-wchar-napi` is installed. | Param | Type | | --- | --- | | s | string | **Example** ```js > tcc.escapeWchar('öäü') '\\xf6\\xe4\\xfc' > `wchar_t *w = L"${tcc.escapeWchar('öäü')}";` 'wchar_t *w = L"\\xf6\\xe4\\xfc";' ``` ### tcc.DefaultTcc() ⇒ [Tcc](#module_node-tinycc.Tcc) Helper function to create a compile state with the bundled tcc. The function sets the tcclib and include path to the the platform dependent tcc folders. **Kind**: static method of [node-tinycc](#module_node-tinycc) ### tcc.CFuncType(restype, args, [variadic]) ⇒ function Wrapper for lazy evaluation of a ffi.ForeignFunction or ffi.VariadicForeignFunction. This is needed to postpone the creation of the ffi function until we got the real C symbol pointer. **Kind**: static method of [node-tinycc](#module_node-tinycc) | Param | Type | Description | | --- | --- | --- | | restype | string \| object | known type of `ref.types` | | args | Array | array of parameter types | | [variadic] | boolean | indicate a variadic function | ### tcc.c\_callable(restype, name, args, f) ⇒ Declaration Convenvient declaration function to import a function symbol from JS to C code. The function creates a function pointer declaration in C. After calling `CodeGenerator.bindState` the function pointer can be used in C. Example usage: ```js let callback = tcc.c_callable('int', 'jsfunc', ['int', 'int'], (a, b) => a+b); // use somewhere in C code let decl = tcc.Declaration('int test(int x) { return a * jsfunc(23, 42); }'); gen.addDeclaration(callback); gen.addDeclaration(decl); ... ``` **Kind**: static method of [node-tinycc](#module_node-tinycc) | Param | Type | Description | | --- | --- | --- | | restype | string \| Object | known type of `ref.types` | | name | string | function pointer name | | args | Array | array of parameter types | | f | function | Javascript function | ### tcc.c\_function(restype, name, args, code) ⇒ func Convenient declaration function to create a C function that is usable from Javascript. The Javascript code: ```js tcc.c_function('int', 'add', [['int', 'a'], ['int', 'b']], 'return a+b;'); ``` will roughly translate to this C source code: ```C int add(int a, int b) { return a+b; } ``` Note that the first 3 arguments of `c_function` almost read like the C function header. Additionally the C function will have a forward declaration to use it from any other C code within the same compile state. Returns a proxy function, that automatically resolves to the underlying C function. The actual declaration object resides under `.declaration`. Full usage example: ```js let add = tcc.c_function('int', 'add', [['int', 'a'], ['int', 'b']], 'return a+b;'); let gen = tcc.CodeGenerator(); gen.addDeclaration(add); let state = tcc.DefaultTcc(); state.compile(gen.code()); state.relocate(); gen.bindState(state); console.log(add(23, 42)); // use it ``` **Kind**: static method of [node-tinycc](#module_node-tinycc) **Returns**: func - proxy function | Param | Type | Description | | --- | --- | --- | | restype | string \| Object | known type of `ref.types` | | name | string | function pointer name | | args | Array | array of [type, parameter name] | | code | string | C function body | ### tcc.c\_struct(name, structType) ⇒ StructType Convenient declaration function to declare a struct type usable in C and Javascript. This function extracts the field names and types of a StructType (module `ref-struct-napi`) to create a struct declaration (forward section) and definition for C (code section). A field type is resolved recursively to catch complicated type mixtures that can easily be build with StructTypes, ArrayTypes and pointer types (e.g. `struct XY *(*a[2])[10];`). No typedef declaration is added for the struct, therefore always reference the struct type by `struct name` in C. The struct type can be used at any point where a `ref.types` type is needed, e.g. as function parameter or return type. Usage example: ```js const StructType = require('ref-struct-napi'); let gen = tcc.CodeGenerator(); let S = tcc.c_struct('S', StructType({a: 'int', b: 'char*'})); addDeclaration(S); ``` The struct of the example will roughly translate to this C code (beside some more alignment directives): ```C struct S { int a; char (*b); }; ``` `c_struct` finalizes a `StructType`, i.e. no more fields can be added afterwards. To build a struct type with a pointer to itself (e.g. for linked lists), build the StructType without that field beforehand and use the `StructType.defineProperty` to declare the self pointer member. Decorate the struct type afterwards with `c_struct`: ```js let S = StructType(); S.defineProperty('self', S); c_struct('S', S); // defineProperty not allowed after this ``` **Kind**: static method of [node-tinycc](#module_node-tinycc) **Returns**: StructType - structType decorated with declaration object | Param | Type | Description | | --- | --- | --- | | name | string | struct type name in C | | structType | StructType | structType to be declared in C |