Main
Language
Runtime
Tools
FAQs
Changes
Download
Licence
cheesy

The Idle-TCC interface

This is the preliminary documentation for the Idle-TCC glue module. This module allows you to embed (and execute) live C code from inside your Idle scripts. After a require('TCC') statement all TCC functions are available with the TCC prefix.

Back to the main Idle Runtime library documentation.

Module TCC
top of page

The TCC module needs two DLLs to work properly. One is the glue DLL, TCCglue.dll, which forms the interface between Idle and TCC. This DLL, in turn, loads the TCC main DLL libtcc.dll which has to be somewhere in the path. Both libraries are included in the Idle-TCC distribution.

TCC.addIncludePath(tcc,inc)
top of page

This function adds one or more paths to the include file search path for compiler instance tcc. If inc is a string, it must be a path value to add. If inc is a table, it must be an array of such path values. This function has no return value.

TCC.addLibrary(tcc,lib)
top of page

This function adds one or more libraries to the link options for compiler instance tcc. If lib is a string, it must be the name of a valid library file to add. If lib is a table, it must be an array of such names. This function has no return value.

Note: valid libraries for TCC also include DEF files. This allows you to call almost any DLL function from TCC.

TCC.addLibraryPath(tcc,lib)
top of page

This function adds one or more paths to the library file search path for compiler instance tcc. If lib is a string, it must be a path value to add. If lib is a table, it must be an array of such path values. This function has no return value.

TCC.alloc()
top of page

Allocates a new TCC compiler instance and returns it as a userdatum. In case of an error the function returns nil. You can create more than one TCC instance in a script, but not in parallel (this is a limitation of TCC). However, consecutively allocated TCC instances have their own state and keep this state between calls. To free a compiler instance, call TCC.free():

local myTCC=TCC.alloc()
-- ... lots of calls to TCC
TCC.free(myTCC)

TCC.compile(tcc,str)
top of page

This function accepts a string str with C code and attempts to compile it inside compiler instance tcc. The string can be as long or as short as you want and can contain function and variable definitions, but it has to be syntactically correct C. The compiler keeps state between calls to TCC.compile(); this allows to define variables and functions for later use. This function returns true if successful or false and an error message in case of an compile error. See TCC.getSymbol() for an example.

TCC.free(tcc)
top of page

Frees a compiler instance. You must free the current instance before creating a new one.

TCC.getSymbol(tcc,name)
top of page

This functions returns a proxy for a C function defined in compiler instance tcc. This function can then be called like any other Idle function. This allows you to call any compiled C function from Idle. Here is a simple example:

require('TCC')
tcc=TCC.alloc()
TCC.addLibraryPath(tcc,'..\\tcc\\lib')  -- add library path
local b,e=TCC.compile(tcc,[=[  // compile a C function
  int simple(void *L) { // no parameters, no return value
    int i=12;
    int j=24;
    printf("Hello, world... from TCC: %i\n",i*j);
    return 0;
  }
]=])
assert(b,string.format('error in C code: %s',e))
TCC.relocate(tcc)
local simple=TCC.getSymbol(tcc,'simple',1)  -- get address of simple()
simple()  -- and call it
tcc=nil

TCC.relocate(tcc)
top of page

This function relocates and links all compiled code inside compiler instance tcc. It has to be called after compiling all the required C code strings (see TCC.compile()), but before calling TCC.getSymbol() to obtain C functions. The function returns true if successful and false otherwise.

TCC.new(boff,incp,libp,libs)
top of page

This function is an example wrapper, one of many possible implementation strategies to access TCC from Idle in a simple and efficient manner. It returns a table t with the following elements:

The boolean parameter boff, if true, switches off Idle's buffering of stdout. Unbuffered output may be necessary if both Idle and TCC write to stdout. The remaining three parameters, if specified, initialise the include path(s), library path(s) and add one or more libraries.

Here is a simple, but complete example:

require('TCC')
local incp={'..\\tcc\\include','..\\..'} -- set include paths
local libp='..\\tcc\\lib'                -- set library path
local libs='idle03'                      -- loads Idle03.def
local tc=TCC.new(true,incp,libp,libs)    -- let's grab a compiler
local C=tc.compile  -- a few shortcuts to compile and link C code
local L=tc.link
local F=tc.getFunction

-- compile two C functions
local b,e=C[=[
  #include <stdio.h>
  #include <lua.h>
  #include <lauxlib.h>

  int simple(void *L) { // no parameters, no return value
     int i=12;
     int j=24;
     printf("Hello, world... from TCC: %i\n",i*j);
     return 0;
  }

  int slightyLessSimple(lua_State *L) {
     // two double parameters, two double returns
     double i=(double)luaL_checknumber(L,1);
     double j=(double)luaL_checknumber(L,2);
     printf("d1*d2=%10.4f\n",i*j);
     printf("d1/d2=%10.4f\n",i/j);
     lua_pushnumber(L,i*j);
     lua_pushnumber(L,i/j);
     return 2;
  }
]=]

assert(b,string.format('error in C code: %s',e))
L()  -- finished with compiling, link the generated code
local simple=F('simple')  -- get address of function simple()
print('1.')
simple()                  -- call it

local slightyLessSimple=F('slightyLessSimple')
print('\n2a.')
print(slightyLessSimple(456.2,23.9))
print('\n2b.')
print(slightyLessSimple(math.pi,17.01^2))


$$ built from IdleTCC.txt d106963c4f77 Mon Sep 27 13:27:10 2010 +0000 thomasl $$