CritclはTclのソースにCなどのコードを埋め込んで、"on the fly"にコンパイルする拡張です。PerlでいうところのinlineCです。速くなると思います。ベンチマークも取ってみたいと思います。

***改造 [#gf70e472]
いまのとこ(critcl0.34)Windows+mingwではgccのコマンドパスの作成がちょっとおかしくてそのままだとコンパイルできないので、改造します。ていうか、空白パスをエスケープしたりするだけなんですが。単純にWindowsだとホームディレクトリへのパスに空白があるので、
 C:/Documents and Settings/MyAccount/.critcl   //FAIL
 C:/Documents\ and\ Settings/MyAccount/.critcl //OK
と適当に引っ掛かるところだけエスケープするだけです。面倒なので差分だけ置いておきます。
 *** critcl.vfs.old\lib\critcl\critcl.tcl	Wed Dec 22 19:30:55 2004
 --- critcl.vfs\lib\critcl\critcl.tcl	Mon May 02 20:23:23 2005
 ***************
 *** 35,40 ****
 --- 35,43 ----
                   cdata compiling scripting failed done tk cache tsources \
                   platform cheaders cdefines
   
 +   proc escape {str} {
 +     return [string map {{ } {\ }} $str]
 +   }
     # ouch, some md5 implementations return hex, others binary
     if {[string length [md5 ""]] == 32} {
       proc md5_hex {s} { return [md5 $s] }
 ***************
 *** 584,590 ****
         if {$v::options(I) != ""} {
           lappend copts -I$v:::options(I)
         }
 !       lappend copts -I$cache
         set copies {}
   
         foreach x $hdrs {
 --- 587,593 ----
         if {$v::options(I) != ""} {
           lappend copts -I$v:::options(I)
         }
 !       append copts "-I[escape $cache]"
         set copies {}
   
         foreach x $hdrs {
 ***************
 *** 598,604 ****
  	 }
         }
   
 !       set cmdline "$v::compile $copts -o $libfile $base.c $srcs"
         if {$v::options(language) != ""} {
   # Allow the compiler to determine the type of file
   # otherwise it will try to compile the libs 
 --- 601,607 ----
  	 }
         }
   
 !       set cmdline "$v::compile $copts -o [escape $libfile] [escape $base.c] $srcs"
        if {$v::options(language) != ""} {
  # Allow the compiler to determine the type of file
  # otherwise it will try to compile the libs 
他にも直すところがあるかもしれません。

***基本的な使い方 [#cfc70bd2]
-gccがインストールされていないといけません。
-コンパイルされたdll/soは~/.critclにキャッシュされます。

 package require critcl
 
 critcl::cproc add {int a int b} int {
     return a + b;    /* this is C code */
 }
 
 critcl::cproc addf {double a double b} double {
     return a + b;    /* this is C code */
 }
char型、配列、ポインタはこの方法では引数に渡せない(?)ようです。

***Cのヘッダファイルなどを埋め込み [#ca1838fd]
 package require critcl
 
 critcl::ccode {
 	#include <stdio.h>
 	#include <stdlib.h>
 }
 
 critcl::cproc testput {} void {
 	char *str = malloc(sizeof(char)*100);
 	int i;
 	for (i=0; i<100; i++) 
 		sprintf(str+i, "%d", i%10);
 	
 	for (i=0; i<10; i++) 
 		printf("%c\n", str[i]);
 	
 	free(str);
 	return;
 }

*** Cのファイルとリンク[#j1f0bbe8]
counter.h 
 #ifndef _DEF_H_COUNTER
 #define _DEF_H_COUNTER
 extern int incrCount();
 extern int CountVal;
 #endif

counter.c
 #include "counter.h"
 int CountVal = 0;
 int incrCount()
 {
 	return ++CountVal;
 }

test.tcl
 package require critcl
 
 critcl::cheaders counter.h
 critcl::csources counter.c
 
 critcl::ccode {
 	#include <stdio.h>
 	#include <stdlib.h>
 	#include "counter.h"
 }
 
 critcl::cproc countUp {} void {
 	int i;
 	for (i=0; i<10; i++) {
 		incrCount();
 		printf("%d\n", CountVal);
 	}
 	return;
 }

***ライブラリの作成 [#xae0c10d]
critclではライブラリを作ることもできます。~
test.tcl
 package require critcl
 
 critcl::cproc add {int a int b} int {
     return a + b;    /* this is C code */
 }
 
 critcl::cproc addf {double a double b} double {
     return a + b;    /* this is C code */
 }

これをライブラリにするには、
 tclkit critcl.kit -lib test.tcl
とすると、test.dllが作成されます。これを使うには普通にtclshで
 load test.dll
などとしてやればいいです。Win,Mac,UNIXでMakefileを書き分けたりせずに簡単にコンパイルできるのが楽でいいと思いましたです。

***ライブラリの作成(パッケージ) [#d2731e91]
パッケージにすることもできます。~
cmath.tcl
 package require critcl
 
 package provide cmath 1.0
 
 namespace eval cmath {
 	critcl::cproc add {int a int b} int {
 	    return a + b;    /* this is C code */
 	}
 	
 	critcl::cproc addf {double a double b} double {
 	    return a + b;    /* this is C code */
 	}
 }

 tclkit critcl.kit -pkg test.tcl

libディレクトリ以下にパッケージを作ります。
~
lib以下にはターゲットマシンごとのライブラリが存在します。が、特定のプラットフォーム決め撃ちの時はpkgIndex.tclに次のように書いておけばpkgIndex.tclとライブラリの二つのファイルだけでいけます。
 package ifneeded cmath 1.0 " 
 	package provide cmath 1.0; 
 	[list load [file join $dir cmath.dll] cmath]; 
 "

***ベンチマーク(たらいまわし) [#r4656001]
 source critcl.kit
 package require critcl
 
 proc tcl_tak {x y z} {
 	if {$x <= $y} {return $z}
 	return [tcl_tak \
 		[tcl_tak [expr $x-1] $y $z] \
 		[tcl_tak [expr $y-1] $z $x] \
 		[tcl_tak [expr $z-1] $x $y] \
 	]
 }
 
 critcl::ccode {
 	static int tak (int x, int y, int z)
 	{
 		if (x<=y) return z;
 		return tak(
 			tak(x-1, y, z),
 			tak(y-1, z, x),
 			tak(z-1, x, y)
 		);
 	}
 }
 
 critcl::cproc c_tak {int x int y int z} int {
 	return tak(x,y,z);
 }
 
 set x 20
 set y 10
 set z 5
 puts "Tcl [time {tcl_tak $x $y $z} 10]"
 puts "C   [time {c_tak $x $y $z} 10]"

一回目
 Tcl 1614874 microseconds per iteration
 C   93094 microseconds per iteration
二回目
 Tcl 1612537 microseconds per iteration
 C   3317 microseconds per iteration

注:一回目はCのコードをコンパイルするので遅いです。
***コメントをどーぞ [#v624aabe]
#comment

----
[[CategoryTclTk]]

HTML convert time: 0.002 sec.