[Critcl Logo] A shortcut for [Critcl builds C extensions on-the-fly] The name stands for '''Compiled Runtime In Tcl'''. * The Critcl homepage is http://www.equi4.com/starkit/critcl.html * The main repository is at https://github.com/jcw/critcl ** With homepage at http://jcw.github.com/critcl/ * A backup is at https://github.com/andreas-kupries/critcl ** With homepage at http://andreas-kupries.github.com/critcl/ * [Arjen Markus] is working on a Fortran extension - [Critcl goes Fortran] ---- 2011-10-20 [tjk] '''Critcl3''' has just been released and is available at '''http://jcw.github.com/critcl/%|%Critcl Home%|%'''. This site is the new home for Critcl development. ---- 2008-03-02 [JMN] '''Presumably''' the latest version of critcl can be obtained using '''svn co svn://svn.equi4.com/critcl/trunk critcl.vfs''' as mentioned below. I say presumably because it should be noted that there are other components within the checked out structure that are out of date. (e.g md5, snit) The critlib set of packages linked from the critcl homepage shows critcl version 0.33, whereas as at 2008-03-02 the svn source contains version 2.0 ---- Tcl 2002 conference paper by Steve Landers and Jean-Claude Wippler is at [http://www.digital-smarties.com/Tcl2002/critcl.pdf] as PDF (and online as HTML at [http://www.equi4.com/papers/ctpaper1.html]), with slides from [JCW]'s presentation at [http://www.equi4.com/docs/vancouver/pres2.htm]. [Zarutian] 14. august 2007: does critcl require an external compiler? [AK]: AFAIK yes. [Zarutian] 15. august 2007: got any pointers to machine code generators or compilers that dont require extensive environment? [AK]: See [tcc], and also [Scripted Code Generation]. [Critcl Manual] is a first cut at trying to pull a manual together. Below are some simple how-to examples. [Critcl Examples] has links to other pages. ---- '''Using inlined C code''' * make sure you have a working gcc (or mingw) setup * get the [critlib] distribution and unpack [http://www.equi4.com/critlib/critlib.tar.gz] * create a test script called "three.tcl" with the following contents: lappend auto_path . package require critcl critcl::cproc triple {int i} int { return i * 3; /* this is C code */ } puts "three times 123 is [triple 123]" * run the above script (using tclsh, [tclkit], whatever), e.g. tclkit three.tcl * that's it - you should see the result of compiled C code * [SC] fixed typo in code above, it had critcl::ccode instead of critcl::cproc, ditto below ---- '''Building an extension for general use''' * get [Steve Landers]' Critcl [Starkit] from [http://www.equi4.com/pub/sk/critcl.kit] and rename to "critcl" * note that you do not need to get critlib (but you do need a working gcc) * get a suitable copy of "tclkit" and make sure it works, see [http://www.equi4.com/starkit/37] * you can get on-line help by doing "tclkit critcl" * create a test script called "four.tcl" with the following contents: package provide four 1.0 package require critcl critcl::cproc quadruple {int i} int { return i * 4; /* this is C code */ } * you can now turn it into a shared library extension with one command: cd /path/where/four.tcl/lives/ tclkit /path/to/critcl -pkg four.tcl : and the result is: Source: four.tcl Library: four.so Package: /path/where/four.tcl/lives/lib/four * to test it, you could use the following script: lappend auto_path lib package require four puts "four times 123 is [quadruple 123]" * note that critcl is no longer required when using this extension * the "four" extension is TIP55 compliant and can be used with any stub-enabled release of Tcl ---- '''Cross compiling using [Xmingwin]''' Critcl supports cross compiling libraries and packages for Windows on Linux/Unix using the Xmingwin cross-compiler (based on mingw - http://www.mingw.org). * Once you are successful at [Xmingwin installation], you'll need to set your PATH to include the Xmingwin bin directory before using Critcl. One convenient way of doing this is to create a script called ''cross'' (in /usr/local/bin or ~/bin). $ cat /usr/local/bin/cross PATH=/usr/local/Xmingwin/i386-mingw32msvc/bin:$PATH export PATH exec $@ * Then, you can compile using the usual Critcl package (or library) building commansd $ cross critcl -pkg four.tcl Cross compiling for Windows using Xmingwin Source: four.tcl Library: four.dll Package: /path/to/four/lib/four * If Critcl recognizes a cross compile environment, it manipulates the tcl_platform array so that it matches that found on Windows 2000. Specifically, the following values are set tcl_platform(byteOrder) = littleEndian tcl_platform(machine) = intel tcl_platform(os) = Windows NT tcl_platform(osVersion) = 5.0 tcl_platform(platform) = windows tcl_platform(wordSize) = 4 * Critcl also provides the '''[[critcl::sharedlibext]]''' procedure, which returns the shared library extension for the target platform. If you plan on cross-compiling you should use this variable in your Critcl scripts instead of '''[[info sharedlibextension]]''' (although overlaying the '''info sharedlibextension''' command will probably happen at some stage). * Intermediate files are stored in '''~/.critcl/Windows-x86''' irrespective of the platform on which cross compiling occurs For an example, download http://www.tcl.tk/starkits/critex.tar.gz, unload and change to the ex2/ directory. This contains a blowfish extension for Tcl. To build on Linux/Unix, run $ critcl -pkg blowfish Source: blowfish.tcl Library: blowfish.so Package: /path/to/ex2/lib/blowfish Then, to cross compile (via the above '''cross''' script) run $ cross critcl -pkg blowfish Cross compiling for Windows using Xmingwin Source: blowfish.tcl Library: blowfish.dll Package: /path/to/ex2/lib/blowfish If you look under ex2/lib/blowfish you'll see lib/blowfish lib/blowfish/critcl.tcl lib/blowfish/pkgIndex.tcl lib/blowfish/Windows-x86 lib/blowfish/Windows-x86/critcl.tcl lib/blowfish/Windows-x86/blowfish.dll lib/blowfish/Linux-x86 lib/blowfish/Linux-x86/critcl.tcl lib/blowfish/Linux-x86/blowfish.so The pkgIndex.tcl will autoload the correct binary for a particular platform. ---- ''Aug 2007'' - Critcl sources are now in [SVN]: svn co svn://svn.equi4.com/critcl/trunk To create a starkit from it, also do: ln -s critcl critcl.vfs sdx wrap critcl.kit -[jcw] ---- Discussion below moved from [Scripted Compiler] to the more natural place. [AM] Because of Critcl I am working on a package that abstracts the concept of a compiler and a linker away from the platform-dependencies. This way Critcl will be able to support "any" compiler/linker without the user (or the Critcl programmer) having to jump through hoops. [Vince] That sounds great! [Victor] Without linker ?? How then I use gcc produced *.o or archives ? That is Critcl libs should take this place. Are they encrypted ? And it is still a long way to have it accepted by many people. [NEM] There is [Babel], by Paul Duffin. However, like Feather, it may take a while to get hold of any code from Paul. ---- "How to use C and Tcl Together" [http://www.cuj.com/articles/2002/0212/0212toc.htm?topic=articles] presents Critcl [[Critcl]] as a profoundly important innovation. ''[escargo] 11/11/2002:'' I got a 404 on this link. [IDG] Me too. The link is up and functional now - [AK]. ''[escargo] 12/5/2002:'' I see a table of contents, but no link to an article. Is it expected that the link above lead to the article itself? ---- Critcl makes a brief appearance in this [http://www-106.ibm.com/developerworks/linux/library/l-sc10.html] column on [XMingwin]. ---- [Critcl does C++] ---- [UKo] How can I inject code into the package initialization section? This is necessary to build new canvas commands or new sound subcommands for [Snack]. [AM] There is a command ''cinit'' that allows you to do this. [UKo] It isn't in the critcl wikit, is it? Where can I find an up-to-date reference? Or do I have to RTSL (Read the source Luke!) [AM] I can send you the (informal) documentation I wrote ... just drop me a mail ---- 29apr03 [jcw] - Here's a trick to make a file work both as Tcl script and as C source: #undef _ /* this is mixed-mode C and Tcl source code package provide mypkg 1 package require critcl critcl::ccode { /* C code follows: */ #ifndef _TCL #include /* etc ... */ #endif /* C code here ... */ #ifndef _TCL int main(int argc, char** argv) { /* standalone code here ... */ } #endif #define _ };#/* Tcl code follows: critcl::cproc proc1 {int v} int { return cdef1(v); } critcl::cproc proc2 {char* s} int { return cdef2(s); } # vim: set ft=c: */ That last line also makes the "vi" editor colorize the file as C code, which is presumably the bulk. The idea is that you can embed large chunks of C in Tcl, with some trivial cproc definitions at the end calling that code, while keeping the file in a form which can also be used in non-Tcl environments, e.g. building code as Tcl extension *and* as a plain C application. The other way to do this is to use "critcl::csources somefile.c" and then to store all C code there, but this stops Critcl from auto-detecting source changes made to such an external file, so its automatic recompile won't kick in. With the above approach, you can edit at will and Critcl will compile (only) when needed, while you get Tcl's context, say for running test suites. The end result can then be used in non-Tcl contexts. ---- Jean-Claude was aware of [Perl]'s Inline [[...]] but not (?) of [Python]'s Weave [[...]] in his design of Critcl. ---- [Ffidl] provides an alternative approach for "calling functions in arbitrary dynamic libraries". Also see "[How to use C functions from Tcl]". ---- [wcf3] Can someone provide an example for using critcl on a MacOSX system as described in '''Building an extension for general use''' above? I have the AquaBI runtime installed and it appears to only find critcl 0.0 instead of version 0.33 that is part of the critcl.kit. The error message I get is that command ''critcl::crosscheck'' is not found (it's part of version 0.33, not 0.0 :-) More info: The AquaBI install included a set of example critcl files called ''critlib'' that required '''critcl 0.30'' and forced the loading of the older version 0.0. By removing the ''critlib'' stuff from /Library/Tcl I am now able to get the proper '''critcl 0.33''' loaded. The problem now is the include files used by '''critcl''' are for X windows and not Aqua...duh, I should have seen that one coming. Any ideas? [CMcC] Critcl needs to allow you to specify arbitrary compiler arguments, which would enable you to use the -I command to select your preferred inclusion places. At the moment, this is not possible. About the only thing I can suggest is using the critcl::cheaders command to specify, individually, the files you want to include (and the files *they* want to include, in some cases) in the correct order. It's quite annoying. [stevel] I regularly do things like critcl::cheaders -I[pwd] critcl::cheaders -L[pwd] -lmylib [Lars H], 8 Feb 2006: Some info on the Critcl/Aqua issue can be found in [http://aspn.activestate.com/ASPN/Mail/Message/2375128]. The important part for simple uses appears to be the command critcl::cheaders -DMAC_OSX_TK -I/Library/Frameworks/Tk.framework/Headers (The -I option can probably be changed so that one doesn't have to specify an explicit path to the Tk framework, but I haven't tried that yet.) ---- '''critcl::cdefines''' - [stevel] Dec 17 2004 critcl::cdefines allows C #defines and enums to be mapped from C into a Tcl namespace. For example, [Cryptkit] uses the following to map Cryptlib symbols (i.e. #defines and enums) into the cryptkit namespace # map Cryptlib #defines and enums into the current namespace critcl::cdefines CRYPT_* [namespace current] # other defines critcl::cdefines { NULL TRUE FALSE TCL_OK TCL_ERROR } [namespace current] ---- [RLH] 2009-04-11: Is Critcl going to be in teapot (for OSX)? I remember there being a problem with that platform. I think... [AK] Critcl is not in the teapot, for no platform. Are you possibly confusing critcl with tcllibc ? That is a shared library created from a number of critcl based code found Tcllib and accelerating a few packages of it. [stevel] further to that, Critcl works just fine on OSX - it even generates universal binaries by default. [AK] whereas some of the critcl code in Tcllib indeed fails on OS X, for ... I do not remember the reason. Possibly header trouble. [RLH] Maybe my old brain is failing me. :-) ---- [AMG]: Critcl doesn't mix smoothly with namespaces. ====== package require critcl namespace eval foo {} critcl::cproc foo::successor {int x} int {return x + 1;} foo::successor 5 ====== The above results in a bunch of errors that stem from Critcl attempting to create a C function named "foo::successor". The trick is to not put any namespace qualifiers in cproc's first argument. I think the best approach is to call cproc inside [namespace eval]. ====== package require critcl namespace eval foo { critcl::cproc successor {int x} int {return x + 1;} } foo::successor 5 ====== Or use [rename] to move the command into the right namespace. But there's a huge gotcha: the command doesn't exist until the first time it's called! Instead of calling the command, [auto_load] can be used to force its creation. ====== package require critcl namespace eval foo {} critcl::cproc successor {int x} int {return x + 1;} auto_load successor rename successor foo::successor foo::successor 5 ====== ---- See [photo image equality in Critcl] for how to speed up Tcl code 1200 times :^) ---- '''[CMcC] - 2010-05-05 20:13:12''' I have sought to modularize and simplify critcl, and have denuded of features in a work in progress I call [C.tcl] In part, this is an attempt to open critcl up to critical appraisal by simplifying it and making it more transparent. [AMG]: I look forward to the completion of this project. ---- [AMG]: Critcl has an interesting [gotcha] that will bite you when you divide your code into multiple Tcl scripts that are [[[source]]]d into the same program. Critcl uses [[[info script]]] to determine which cprocs, etc. to compile in the same translation unit (compiler invocation). If you have cprocs across multiple scripts that depend on being compiled together (e.g. they share a common ccode definition), you will have to use [[info script $filename]] to force Critcl to think all cprocs are in the same script. Alternately, instead of using [[source]], put your cprocs in files external to your Tcl code, and [[[read]]] them to get the arguments to cproc. This has the dubious advantage of letting you separately specify a C syntax highlighting mode for your cproc files and a Tcl syntax highlighting mode for your Tcl files. You can also implement a custom preprocessor this way. [AK]: There are actually two more [gotcha]s in critcl. The first is about the differences between the ''dynamic'' and ''pre-compiled'' modes (my names, not official) of critcl. For context, critcl can be used in two ways. For one you load your Tcl code with the embedded C as usual, this internally runs the compiler and loads the object files into the system. This is the ''dynamic'' mode. The other way is to run the Tcl with embedded C through the critcl application, this generates a shared library for the C commands, which can be loaded later. This is ''pre-compiled''. The difference is in the Tcl code between the embedded C sections. The dynamic mode runs them as usual. The shared library which is the result of the ''pre-compile'' step does not have them. If these commands just initialize the namespace the C commands will end up in we are fine. Anything beyond that however meas that the result of the pre-compile step behaves differently than the code run dynamically, with essential/expected setup missing. The other gotcha is again in the interaction of pre-compiled results with the regular critcl package handling dynamic execution. First, pre-compiled results define a rudimentary critcl package which has all the commands empty. That isn't so bad. Load the actual package and it will overwrite the empty pieces with the proper definitions. Except that you are not able to load your proper package. Because the rudimentary package actually also runs 'package provide critcl 0', and this code is run when the pkgIndex.tcl file is read, i.e. this fake critcl package gets defined just by loading any other package forcing a search. At this point a 'package require critcl' either throws an error (version conflict, want X, have 0), or does nothing (no specific version was requested, the fake satisfies the request). If you now want to run some critcl code dynamically you will get an error about missing commands, because the critcl support commands like cproc/ccommand which we expected to define them were of the fake and did nothing at all. Looking at the fake critcl package I have no idea why it was made in the first place. Well, partially to handle the package load, but for that we do not have to declare the relevant commands to be a package. Just having them is good enough. I was certainly able to fix my trouble by commenting out all the 'package provide critcl 0' commands in all the tcllibc versions I had around. Tcllibc still loaded, and now the real critcl package was accessible too. ---- **Similar Projects** [Odyce] and [tcltcc] partially emulate the Critcl API. <> Critcl | Development