- The added line is THIS COLOR.
- The deleted line is THIS COLOR.
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.005 sec.