''Source code is now at http://www.equi4.com/critlib/ - [JCW]'' * Version 0.18 now runs on Linux and Windows (MinGW) * As of 0.22, you can store the binaries generated in a specific directory with a more meaningful name * source is now up to 0.28 (2001-Nov-21) ---- It is not clear, after reading this page, exactly what files have to be installed on a Windows machine to use CriTcl. Does one have to install the critcl source code and then some other piece(s)? ''June 2002'' - Yes, you need critcl installed as a normal Tcl package (i.e. so "package require critcl" works in tclsh or tclkit) and you need to set things up so "gcc" works. What I do is install the mingw system, and set up the PATH so "gcc" works from the command line. That's it. -jcw ---- See also Richard Suchenwirth's [C code generators] page. ---- The '''C Runtime In Tcl''' is a self-contained package to build C code into an extension on the fly. It is somewhat inspired by Brian Ingerson's Inline for Perl, but CriTcl is considerably more lightweight. [[While [Python] also has an Inline [http://pyinline.sourceforge.net/], it apparently has no direct genetic connection to CriTcl.] The idea is to wrap C code into something that will compile into a Tcl extension, and then also fire up the compiler. Compiled chunks will be cached in your ~/.critcl/ directory, so subsequent use will be instant. The main definition is "critcl::cproc", which lets you define a (surprise) C proc, with C code as body. Args and return values must be typed. There are no default args or ways to pass more sophisticated data items than int/long/float/double/char* for now. There is also a "critcl::ccode" call, to inject C code as is, and a "ccommand" call, which ties code to the Tcl_CreateObjCommand without further wrapping. The use of Tcl stubs, and the fact that this extension has all include files it needs to make compilation self-contained, means that this is a pure Tcl package, which should work with any (8.1 and up) installation of Tcl. Most importantly, CriTcl does not care a bit where Tcl was installed, nor even whether it was built as a static or as a dynamic executable. This is a working demo, but it is still young. It will for now blindly use "gcc" to do the compile and has somewhat rudimentary error handling. CriTcl has been verified to work on Linux and Win NT4 (MinGW) so far. ---- Works on Win98 with mingw. [IDG] ---- Oh, one more thing: this code assumes the md5 command is available. ---- ''There's a new CritLib package with several extensions (blowfish, hexdump, ihash, lazy, lzrw1, md5c, mvector, noop, rchan, zlib) - see http://www.equi4.com/critlib/'' ---- Source: ---- package require critcl namespace import critcl::* cproc noop {} void {} cproc add {int x int y} int { return x + y; } cproc cube {int x} int { return x * x * x; } puts "add 123 456 : [add 123 456]" catch {add 1} err; puts "add 1 : $err" catch {add 1 2 3} err; puts "add 1 2 3 : $err" catch {add 0 zero} err; puts "add 0 zero : $err" proc sum {a b} { return [expr {$a+$b}] } proc pow3 {a} { return [expr {$a*$a*$a}] } proc ntimes {n cmd t} { set on $n set r {} while {[incr n -1] >= 0} { lappend r $cmd } set v [uplevel 1 [list time [join $r {; }] $t]] return [lreplace $v 0 0 [expr {[lindex $v 0]/(1.0*$on)}]] } puts "" puts "Tcl noop: [ntimes 100 {} 1000]" puts " C noop: [ntimes 100 {noop} 1000]" set a 1 set b 2 puts "" puts "Tcl expr: [ntimes 100 {expr {1+2}} 1000]" puts "Tcl vars: [ntimes 100 {expr {$a+$b}} 1000]" puts "Tcl sum: [ntimes 100 {sum 1 2} 1000]" puts " C add: [ntimes 100 {add 1 2} 1000]" puts " C vars: [ntimes 100 {add $a $b} 1000]" puts "" puts "Tcl expr: [ntimes 100 {expr {2*2*2}} 1000]" puts "Tcl vars: [ntimes 100 {expr {$b*$b*$b}} 1000]" puts "Tcl pow3: [ntimes 100 {pow3 2} 1000]" puts " C cube: [ntimes 100 {cube 2} 1000]" puts " C vars: [ntimes 100 {cube $b} 1000]" ---- Output (SuSE 7.1 Linux, PIII/650): ---- add 123 456 : 579 add 1 : wrong # args: should be "add x y" add 1 2 3 : wrong # args: should be "add x y" add 0 zero : expected integer but got "zero" Tcl noop: 0.01 microseconds per iteration C noop: 0.67 microseconds per iteration Tcl expr: 0.36 microseconds per iteration Tcl vars: 1.92 microseconds per iteration Tcl sum: 2.51 microseconds per iteration C add: 1.06 microseconds per iteration C vars: 2.66 microseconds per iteration Tcl expr: 0.7 microseconds per iteration Tcl vars: 2.83 microseconds per iteration Tcl pow3: 2.78 microseconds per iteration C cube: 0.96 microseconds per iteration C vars: 1.81 microseconds per iteration ---- [AK] Ideas * Replace the current blind usage of gcc with calls into a tcl based build system to make this code platform independent. * Make code in tcllib conditional on the availability of such a build system. I.e. Pure Tcl if there is no build system, and compiled code else. * With an omni-present build system we can do away with the restriction of not using C code / extensions in Tcllib. -- Later -- But the build system is not omnipresent, unfortunately. So scratch this idea. * [deployment] of C extensions in wrapped application becomes easy. Code is deployed in source and compiled and cached on site. But relies on presence of a compiler on the site. -- Later -- Which makes this a not so good idea after all. * Alternative is to compile before deployment and use the existing methods to load the code dynamically. * The ideas above require that Build system and CriTcl are distributed along with the core itself, like http, dde, and reg. ---- I don't follow most of the AK ideas above. My impression was that the reason for the "no compiled code" rule in tcllib was because we did not want to require a compiler on the user's machine in order for the user to use all of tcllib. There's nothing here that provides a compiler, so I don't see how the nifty features provided by CriTcl change anything about whether or not to include C-coded packages in tcllib. '''DGP''' (Please read the above as "AK's ideas", not mine) I am not sure that extending CriTcl to create a build system of some sort would be my first goal. The model I have is a group of developers, all fed up with build issues (and with a standard C compiler within reach at all times), and the rest of the world (trying to never have to find out what a "compiler" is, let alone allow one on their machine). In this context, CriTcl is way cool for developers IMO, yet useless for the majority of people on this planet. For deployment, I always use TclKit. Once CriTcl gains the capability to build all C packages into either a shared or a static lib, it will be helpful for any developer with the same type of machine as their clients to press a button, wrap all C code up, package the app into some standalone system (not necessarily TclKit of course), and never look back. From where I stand, the best delivery mode '''to''' developers is source code (unless it's so standard that a binary is more convenient and is supplied by a trusted source), while the best deployment mechanism to reach everyone else is always: portable scripts + binaries, usually wrapped up in some way. Does CriTcl need a build system? I'm not convinced... - '''JCW''' [AK] Clarifications. * What Donal says is essentially correct and I have now added clarification to the items which were not so good ideas after all. * I am not sure how this thought came to be, but I did not advocate to use CriTcl to create a build system. What I did thought about was to take whatever build system will come out of TIP 34 and 59 and sucessors and let CriTcl use that instead of hardcoding the usage of gcc into it. [PT] 2003-May-02: For an example of '''optionally''' extending [tcllib] using [critcl] have a look at the [md4] module and the DEVELOPMENT branch of the [base64] module (specifically the [uuencode] and [yencode] packages). These files include C code to be built with critcl. If tcllib is being packages as a [starkit] or [starpack] then using critcl to build the base64c, md4c and md5c packages will enable compiled code for the supported platform. Critcl packages are already installed into a platform dependent subdirectory so for supported packages we get normal tcllib functionality with compiled speed, while for other platforms we still have the pure tcl versions. Personally I think this is the best of all worlds. ---- Has someone looked at http://root.cern.ch/root/Cint.html as a possible way to integrate C with Tcl without having to compile C... ---- [AK]: [Larry Virden] provided this pointer: http://www.purl.org/NET/Tcl-FAQ/part4.html What: Embedded C (EC) Where: ftp://ftp.reed.edu/pub/users/greaber/ec-0.1.tar.gz Description: Allows you to include C code in your Tcl scripts, compiling and dynamically loading it on the fly. The code will also be cached so the next time you run the program, you don't wait for it to compile. Known to work on DEC OSF/1 V3.2 and SunOS 5.5. Not yet ported to Macintosh or Windows. Updated: 09/1996 Contact: mailto:greaber@reed.edu (Grant Reaber) ---- [JH]: In order to have this work with [ActiveTcl] (Tcl with tcllib), I had to change the first few lines of the critcl.tcl code to: catch {package require md5} if {[llength [info commands ::md5::md5]]} { interp alias {} ::md5 {} ::md5::md5 } and it provided some very nice performance numbers on just the md5 stuff: (jeffh) 60 % time {md5 hello} 1000 801 microseconds per iteration (jeffh) 61 % time {md5c hello} 1000 4 microseconds per iteration ''The catch... would break if there was already an "md5" command, wouldn't it? In fact, while I think I understand why that code is written in the way it is, is there a way to do things simpler? - JCW'' Maybe the following is a solution: if {[catch md5]} { catch {package require md5} } if {[catch md5]} { interp alias {} ::md5 {} ::md5::md5 } It's still extremely messy and weak (brittle) IMO, and illustrates how we seem to be making it harder and harder to write readable, clean, solid code... ''':-(''' ---- A dated article [http://www.itworld.com/AppDev/710/swol-0818-regex/] has background information on interpreted C. ---- More news on newer rev's of CriTcl, or rather the "CritLib" where it is included: * There's a '''critcl::config''' to specify things like: '''outdir''' - putting all compiled extensions in a fixed dir, using a normal (non-MD5-ized name), and '''keepsrc''' - do not delete the generated intermediate C source code * There's a '''critbind''' script which takes one or more CriTcl packages, and turns them into a single deliverable: either a loadable extension, or a static lib (for linking later), or an application. The latter is usually called a "custom tclsh", it can be built either as small main linked to Tcl dynamically, or as bigger exe with all of Tcl linked in statically '''JCW''' ---- [LV]: Has anyone investigated making use of CriTcl to create an HTML rendering widget, perhaps based on [BrowseX]? [JCW]: Yep, Tkhtml can be built with CriTcl, though it's tricky. See [http://www.equi4.com/critlib/rhtml.README], now in critlib. ---- [CMcC]: I'm a big fan of [SWIG], but it's so much easier to deliver extensions (at least small ones) with CriTcl because you can put the whole extension into only one source object, where SWIG source distribution requires at least an interface description, a Makefile (to be useful) and (usually) a .tcl to wrap and sugar it up. You can generate the .so file into ., and package it up as a .tar.gz having run it once. Very convenient. I don't understand why setting the outdir to local stops automatic recompilation. There doesn't seem to be any really good reason for that, and it gave me a few unexpected results. I don't see the problem with expecting the user to install Ming under Windows - it's free after all. Compilation errors could perhaps be thrown, so you don't have to root around in ~/.critcl to find out what happened, and the special case of a lack of C compiler could be handled by a URL for downloading a free C compiler under Windows. I'm presuming most people have gcc under Unix. Finally, since tclkit can handle .so and .dll loading, and CriTcl can produce them on the developer's machine, and since CriTcl gives you the significant win of being able to package a whole small extension into a single .tcl, I think it's a win for both binary and source distributions. ---- Thanks for the comments, Colin. The critcl mechanism is still in flux, the most recent work has been to create a self-contained package. It does catch and present errors somewhat better. The "outdir" mechanism is tricky (several features still are quite experimental), but with the packaged version of critcl (by Steve Landers, see [http://mini.net/sdarchive/]) it is no longer needed. See the [Critcl] page, which has just been updated with more info and examples. Your comments in the last paragraph are exactly why I think the use of "outdir" is already becoming less important. What I tend to do is develop inline, and simply never bother about how binaries are dealt with, and then when it's ready for deployment, I run "critcl -pkg myscript.tcl" to create shared libs. -[jcw] ---- Sep 2002 - Conference paper by Steve Landers and Jean-Claude Wippler is now at [http://www.digital-smarties.com/Tcl2002/critcl.pdf], with slides from [JCW]'s presentation at [http://www.equi4.com/docs/vancouver/pres2.htm]. [Category Package] ---- [SWT]: I have built a working cint shared lib for tcl. It works great! Now to "run" c code the cint library is only needed for each platform that support is required for. ---- [Paolo Noli]: A little question: How to call a tcl commands from inside a c funcion declared with the statement "ccode"? (I need this to implement a callback procedure.. but I think this can be an interesting tip for others people. :)