Documentation Index Fetch the complete documentation index at: https://mintlify.com/TinyCC/tinycc/llms.txt
Use this file to discover all available pages before exploring further.
After compilation and linking, you can either run the code in memory or generate an output file.
Memory relocation
tcc_relocate
Performs all relocations needed to run the compiled code in memory. This must be called before using tcc_get_symbol().
int tcc_relocate (TCCState * s );
Returns 0 on success, negative value on error.
Example:
if ( tcc_relocate (s) < 0 ) {
fprintf (stderr, "Relocation failed \n " );
return 1 ;
}
// Now you can get symbols
void ( * func)( void ) = tcc_get_symbol (s, "my_function" );
Do not call tcc_relocate() if you’re using tcc_output_file() or tcc_run(). Those functions handle relocation internally.
Running code directly
tcc_run
Compiles, links, and runs the main() function directly. Do not call tcc_relocate() before this.
int tcc_run (TCCState * s , int argc , char ** argv );
Number of command-line arguments to pass to main().
Array of command-line arguments.
Returns the value returned by the compiled main() function.
Example:
No arguments
With arguments
TCCState * s = tcc_new ();
tcc_set_output_type (s, TCC_OUTPUT_MEMORY);
const char * code =
"#include <stdio.h> \n "
"int main() { \n "
" printf( \" Hello from compiled code! \\ n \" ); \n "
" return 0; \n "
"} \n " ;
tcc_compile_string (s, code);
// Run main() with no arguments
int exit_code = tcc_run (s, 0 , NULL );
printf ( "Program exited with code: %d \n " , exit_code);
tcc_delete (s);
Getting compiled symbols
tcc_get_symbol
Returns a pointer to a symbol (function or variable) from the compiled code. You must call tcc_relocate() first.
void * tcc_get_symbol (TCCState * s , const char * name );
Name of the symbol to retrieve.
Pointer to the symbol, or NULL if not found.
Example:
Getting functions
Getting variables
Getting structs
TCCState * s = tcc_new ();
tcc_set_output_type (s, TCC_OUTPUT_MEMORY);
const char * code =
"int add(int a, int b) { return a + b; } \n "
"int multiply(int a, int b) { return a * b; } \n " ;
tcc_compile_string (s, code);
tcc_relocate (s);
// Get function pointers
int ( * add_func)( int , int ) = tcc_get_symbol (s, "add" );
int ( * mul_func)( int , int ) = tcc_get_symbol (s, "multiply" );
if ( ! add_func || ! mul_func) {
fprintf (stderr, "Failed to get symbols \n " );
return 1 ;
}
// Call the functions
printf ( " %d + %d = %d \n " , 5 , 3 , add_func ( 5 , 3 ));
printf ( " %d * %d = %d \n " , 5 , 3 , mul_func ( 5 , 3 ));
tcc_delete (s);
tcc_list_symbols
Lists all global symbols and their values via a callback function.
void tcc_list_symbols (TCCState * s , void * ctx ,
void ( * symbol_cb)( void * ctx, const char * name, const void * val));
User data pointer passed to the callback.
symbol_cb
void (*)(void*, const char*, const void*)
required
Callback function called for each symbol.
Example:
void print_symbol ( void * ctx , const char * name , const void * val ) {
printf ( "Symbol: %s at %p \n " , name, val);
}
const char * code =
"int var1 = 10; \n "
"int var2 = 20; \n "
"void func1(void) {} \n "
"void func2(void) {} \n " ;
tcc_compile_string (s, code);
tcc_relocate (s);
// List all symbols
tcc_list_symbols (s, NULL , print_symbol);
// Output:
// Symbol: var1 at 0x...
// Symbol: var2 at 0x...
// Symbol: func1 at 0x...
// Symbol: func2 at 0x...
Advanced execution patterns
Plugin system
// Plugin interface
typedef struct {
const char * name;
void ( * init)( void );
void ( * execute)( void );
void ( * cleanup)( void );
} Plugin;
Plugin * load_plugin ( const char * source_code ) {
TCCState * s = tcc_new ();
tcc_set_output_type (s, TCC_OUTPUT_MEMORY);
// Compile plugin
if ( tcc_compile_string (s, source_code) < 0 ) {
tcc_delete (s);
return NULL ;
}
if ( tcc_relocate (s) < 0 ) {
tcc_delete (s);
return NULL ;
}
// Get plugin interface
Plugin * plugin = tcc_get_symbol (s, "plugin" );
if ( ! plugin) {
tcc_delete (s);
return NULL ;
}
return plugin;
}
// Use plugin
Plugin * p = load_plugin (
"#include <stdio.h> \n "
"void my_init() { printf( \" Init \\ n \" ); } \n "
"void my_exec() { printf( \" Execute \\ n \" ); } \n "
"void my_cleanup() { printf( \" Cleanup \\ n \" ); } \n "
"Plugin plugin = { \n "
" .name = \" MyPlugin \" , \n "
" .init = my_init, \n "
" .execute = my_exec, \n "
" .cleanup = my_cleanup \n "
"}; \n " );
if (p) {
p -> init ();
p -> execute ();
p -> cleanup ();
}
Expression evaluator
double eval_expression ( const char * expr ) {
TCCState * s = tcc_new ();
tcc_set_output_type (s, TCC_OUTPUT_MEMORY);
char code [ 1024 ];
snprintf (code, sizeof (code),
"#include <math.h> \n "
"double evaluate() { \n "
" return %s ; \n "
"} \n " , expr);
if ( tcc_compile_string (s, code) < 0 ) {
tcc_delete (s);
return 0.0 ;
}
tcc_add_library (s, "m" );
if ( tcc_relocate (s) < 0 ) {
tcc_delete (s);
return 0.0 ;
}
double ( * evaluate)( void ) = tcc_get_symbol (s, "evaluate" );
double result = evaluate ();
tcc_delete (s);
return result;
}
// Usage
printf ( "2 + 2 = %f \n " , eval_expression ( "2 + 2" ));
printf ( "sqrt(16) = %f \n " , eval_expression ( "sqrt(16)" ));
printf ( "sin(3.14159/2) = %f \n " , eval_expression ( "sin(3.14159/2)" ));
Hot code reloading
typedef struct {
TCCState * state;
void ( * update)( float dt);
void ( * render)( void );
} GameModule;
GameModule * reload_module (GameModule * old , const char * source ) {
// Clean up old module
if (old) {
tcc_delete ( old -> state );
free (old);
}
// Create new module
GameModule * module = malloc ( sizeof (GameModule));
module -> state = tcc_new ();
tcc_set_output_type ( module -> state , TCC_OUTPUT_MEMORY);
if ( tcc_compile_string ( module -> state , source) < 0 ) {
free (module);
return NULL ;
}
if ( tcc_relocate ( module -> state ) < 0 ) {
tcc_delete ( module -> state );
free (module);
return NULL ;
}
module -> update = tcc_get_symbol ( module -> state , "update" );
module -> render = tcc_get_symbol ( module -> state , "render" );
return module;
}
// Main game loop
GameModule * game = NULL ;
while (running) {
// Check if source file changed
if ( source_file_modified ()) {
char * new_source = load_source_file ( "game.c" );
GameModule * new_game = reload_module (game, new_source);
if (new_game) {
game = new_game;
printf ( "Hot reload successful! \n " );
}
free (new_source);
}
if (game) {
game -> update (delta_time);
game -> render ();
}
}
Error handling
void * get_symbol_safe (TCCState * s , const char * name ) {
void * sym = tcc_get_symbol (s, name);
if ( ! sym) {
fprintf (stderr, "Error: Symbol ' %s ' not found \n " , name);
fprintf (stderr, "Available symbols: \n " );
tcc_list_symbols (s, NULL , print_symbol);
}
return sym;
}
// Usage
int ( * func)( int ) = get_symbol_safe (s, "my_function" );
if ( ! func) {
// Handle error
return 1 ;
}