├── .gitignore ├── LICENSE ├── README.md ├── examples ├── add_symbol.lua ├── base.lua ├── compile_exe.lua └── run.lua └── tcc.lua /.gitignore: -------------------------------------------------------------------------------- 1 | /include/ 2 | /lib/ 3 | *.dll 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | luajit-tcc - Tiny C Compiler binding for LuaJIT 4 | 5 | Copyright (c) 2015 Playermet 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy 8 | of this software and associated documentation files (the "Software"), to deal 9 | in the Software without restriction, including without limitation the rights 10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in all 15 | copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | SOFTWARE. 24 | 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Features 2 | - Full support of 0.9.26 API 3 | ```lua 4 | -- Additional OO style for TCCState 5 | tcc.delete(state) 6 | -- or 7 | state:delete() 8 | ``` 9 | ```lua 10 | -- Constants can be used in two ways 11 | state:set_output_type(tcc.const.output_dll) 12 | -- or 13 | state:set_output_type('output_dll') 14 | ``` 15 | # Differences from the C API 16 | Binding is so close to the original API as possible, but some things still differ. 17 | 1. Names lost 'tcc_' prefix as not needed. 18 | 2. 'tcc.add_symbol' and 'tcc.get_symbol' have optional argument for in-place cast. 19 | 3. 'tcc.run' accept table instead of argc-argv pair. 20 | 21 | # Start using 22 | Before calling tcc functions you need to initialize binding with library name or path. 23 | Luajit uses dynamic library loading API directly, so behaviour may be different on each OS. 24 | Filename and location of tcc library may also vary. 25 | Several examples: 26 | ```lua 27 | -- Windows 28 | local tcc = require 'tcc' ('libtcc') 29 | local tcc = require 'tcc' ('../some/path/libtcc.dll') 30 | ``` 31 | 32 | # Example code 33 | ```lua 34 | local tcc = require 'tcc' ('libtcc') 35 | 36 | local state = tcc.new() 37 | 38 | state:set_output_type('output_memory') 39 | 40 | state:compile_string [[ 41 | int summ(int a, int b) 42 | { 43 | return a + b; 44 | } 45 | ]] 46 | 47 | state:relocate('relocate_auto') 48 | 49 | local summ = state:get_symbol('summ', 'int(*)(int,int)') 50 | 51 | print('5 + 7 = ' .. summ(5,7)) 52 | 53 | state:delete() 54 | 55 | ``` 56 | -------------------------------------------------------------------------------- /examples/add_symbol.lua: -------------------------------------------------------------------------------- 1 | local tcc = require 'tcc' ('libtcc') 2 | 3 | local state = tcc.new() 4 | 5 | state:set_output_type('output_memory') 6 | 7 | state:add_symbol('lua_sqrt', math.sqrt, 'float(*)(float)') 8 | 9 | state:compile_string [[ 10 | float lua_sqrt(float); 11 | 12 | float vec2_length(float x, float y) 13 | { 14 | return lua_sqrt(x*x + y*y); 15 | } 16 | ]] 17 | 18 | state:relocate('relocate_auto') 19 | 20 | local vec2_length = state:get_symbol('vec2_length', 'float(*)(float,float)') 21 | 22 | print('length(10,0) = ' .. vec2_length(10,0)) 23 | print('length(10,10) = ' .. vec2_length(10,10)) 24 | 25 | state:delete() 26 | -------------------------------------------------------------------------------- /examples/base.lua: -------------------------------------------------------------------------------- 1 | local tcc = require 'tcc' ('libtcc') 2 | 3 | local state = tcc.new() 4 | 5 | state:set_output_type('output_memory') 6 | 7 | state:compile_string [[ 8 | int summ(int a, int b) 9 | { 10 | return a + b; 11 | } 12 | ]] 13 | 14 | state:relocate('relocate_auto') 15 | 16 | local summ = state:get_symbol('summ', 'int(*)(int,int)') 17 | 18 | print('5 + 7 = ' .. summ(5,7)) 19 | 20 | state:delete() 21 | -------------------------------------------------------------------------------- /examples/compile_exe.lua: -------------------------------------------------------------------------------- 1 | local tcc = require 'tcc' ('libtcc') 2 | 3 | local state = tcc.new() 4 | 5 | state:set_output_type('output_exe') 6 | 7 | state:compile_string [[ 8 | #include 9 | 10 | int main() 11 | { 12 | printf("Hello World!\n"); 13 | getch(); 14 | return 0; 15 | } 16 | ]] 17 | 18 | state:output_file('main.exe') 19 | 20 | state:delete() 21 | -------------------------------------------------------------------------------- /examples/run.lua: -------------------------------------------------------------------------------- 1 | local tcc = require 'tcc' ('libtcc') 2 | 3 | local state = tcc.new() 4 | 5 | state:set_output_type('output_memory') 6 | 7 | state:compile_string [[ 8 | #include 9 | 10 | int main(int argc, char** argv) 11 | { 12 | for (int i = 0; i < argc; i++){ 13 | printf("%s \n", argv[i]); 14 | } 15 | return 0; 16 | } 17 | ]] 18 | 19 | state:run { 1, 2, 3, 'text', false } 20 | 21 | state:delete() 22 | -------------------------------------------------------------------------------- /tcc.lua: -------------------------------------------------------------------------------- 1 | ----------------------------------------------------------- 2 | -- Binding for TCC v0.9.26 3 | ----------------------------------------------------------- 4 | local ffi = require 'ffi' 5 | local jit = require 'jit' 6 | 7 | 8 | local const = {} 9 | 10 | const.output_memory = 0 11 | const.output_exe = 1 12 | const.output_dll = 2 13 | const.output_obj = 3 14 | const.output_preprocess = 4 15 | 16 | const.relocate_auto = ffi.cast('void*', 1) 17 | 18 | 19 | local function get_const(value) 20 | if type(value) == 'string' then 21 | if const[value] then 22 | return const[value] 23 | else 24 | error('unknown const name', 3) 25 | end 26 | end 27 | 28 | return value 29 | end 30 | 31 | 32 | local header = [[ 33 | typedef struct TCCState TCCState; 34 | 35 | TCCState *tcc_new(void); 36 | void tcc_delete(TCCState *s); 37 | void tcc_set_lib_path(TCCState *s, const char *path); 38 | void tcc_set_error_func(TCCState *s, void *error_opaque, void (*error_func)(void *opaque, const char *msg)); 39 | int tcc_set_options(TCCState *s, const char *str); 40 | 41 | int tcc_add_include_path(TCCState *s, const char *pathname); 42 | int tcc_add_sysinclude_path(TCCState *s, const char *pathname); 43 | void tcc_define_symbol(TCCState *s, const char *sym, const char *value); 44 | void tcc_undefine_symbol(TCCState *s, const char *sym); 45 | 46 | int tcc_add_file(TCCState *s, const char *filename); 47 | int tcc_compile_string(TCCState *s, const char *buf); 48 | 49 | int tcc_set_output_type(TCCState *s, int output_type); 50 | int tcc_add_library_path(TCCState *s, const char *pathname); 51 | int tcc_add_library(TCCState *s, const char *libraryname); 52 | int tcc_add_symbol(TCCState *s, const char *name, const void *val); 53 | int tcc_output_file(TCCState *s, const char *filename); 54 | int tcc_run(TCCState *s, int argc, char **argv); 55 | int tcc_relocate(TCCState *s1, void *ptr); 56 | 57 | void *tcc_get_symbol(TCCState *s, const char *name); 58 | ]] 59 | 60 | local bind = {} 61 | local mod = {} 62 | 63 | function mod.new() 64 | return bind.tcc_new() 65 | end 66 | 67 | function mod.delete(s) 68 | bind.tcc_delete(s) 69 | end 70 | 71 | function mod.set_lib_path(s, path) 72 | bind.tcc_set_lib_path(s, path) 73 | end 74 | 75 | function mod.set_error_func(s, opaque, error_func) 76 | bind.tcc_set_error_func(s, opaque, error_func) 77 | end 78 | 79 | function mod.set_options(s, str) 80 | return bind.tcc_set_options(s, str) 81 | end 82 | 83 | function mod.add_include_path(s, pathname) 84 | return bind.tcc_add_include_path(s, pathname) 85 | end 86 | 87 | function mod.add_sysinclude_path(s, pathname) 88 | return bind.tcc_add_sysinclude_path(s, pathname) 89 | end 90 | 91 | function mod.define_symbol(s, sym, value) 92 | bind.tcc_define_symbol(s, sym, value) 93 | end 94 | 95 | function mod.undefine_symbol(s, sym) 96 | bind.tcc_undefine_symbol(s, sym) 97 | end 98 | 99 | function mod.add_file(s, filename) 100 | return bind.tcc_add_file(s, filename) 101 | end 102 | 103 | function mod.compile_string(s, buf) 104 | return bind.tcc_compile_string(s, buf) 105 | end 106 | 107 | function mod.set_output_type(s, type) 108 | return bind.tcc_set_output_type(s, get_const(type)) 109 | end 110 | 111 | function mod.add_library_path(s, pathname) 112 | return bind.tcc_add_library_path(s, pathname) 113 | end 114 | 115 | function mod.add_library(s, libraryname) 116 | return bind.tcc_add_library(s, libraryname) 117 | end 118 | 119 | function mod.add_symbol(s, name, val, ctype) 120 | val = ctype and ffi.cast(ctype, val) or val 121 | return bind.tcc_add_symbol(s, name, val) 122 | end 123 | 124 | function mod.output_file(s, filename) 125 | return bind.tcc_output_file(s, filename) 126 | end 127 | 128 | function mod.run(s, t) 129 | local argc = #t 130 | local argv = ffi.new('char*[?]', argc) 131 | for i = 1, argc do 132 | local str = tostring(t[i]) 133 | argv[i - 1] = ffi.new('char[?]', #str + 1, str) 134 | end 135 | return bind.tcc_run(s, argc, argv) 136 | end 137 | 138 | function mod.relocate(s, ptr) 139 | return bind.tcc_relocate(s, get_const(ptr)) 140 | end 141 | 142 | function mod.get_symbol(s, name, ctype) 143 | local symbol = bind.tcc_get_symbol(s, name) 144 | return ctype and ffi.cast(ctype, symbol) or symbol 145 | end 146 | 147 | 148 | state_mt = {} 149 | state_mt.__index = state_mt 150 | state_mt.delete = mod.delete 151 | state_mt.set_lib_path = mod.set_lib_path 152 | state_mt.set_error_func = mod.set_error_func 153 | state_mt.set_options = mod.set_options 154 | state_mt.add_include_path = mod.add_include_path 155 | state_mt.add_sysinclude_path = mod.add_sysinclude_path 156 | state_mt.define_symbol = mod.define_symbol 157 | state_mt.undefine_symbol = mod.undefine_symbol 158 | state_mt.add_file = mod.add_file 159 | state_mt.compile_string = mod.compile_string 160 | state_mt.set_output_type = mod.set_output_type 161 | state_mt.add_library_path = mod.add_library_path 162 | state_mt.add_library = mod.add_library 163 | state_mt.add_symbol = mod.add_symbol 164 | state_mt.output_file = mod.output_file 165 | state_mt.run = mod.run 166 | state_mt.relocate = mod.relocate 167 | state_mt.get_symbol = mod.get_symbol 168 | 169 | 170 | mod.const = const 171 | 172 | setmetatable(mod, { 173 | __call = function(self, name) 174 | ffi.cdef(header) 175 | 176 | bind = ffi.load(name) 177 | 178 | ffi.metatype('TCCState', state_mt) 179 | 180 | return self 181 | end 182 | }) 183 | 184 | return mod 185 | --------------------------------------------------------------------------------