为tcl编写扩展

绝大多数虚机运行的语言,为了提升速度或访问操作系统API等原因,都需要用能够链接二进制库的语言为其编写扩展。而扩展其实就是为了使链接二进制库的语言与最终调用的虚机语言能够互相理解彼此的类型系统及协调内存管理模式。很多人知道lua拥有一个非常易于扩展的CAPI,而与Perl同时代的Tcl早就具备了这种简练强大的CAPI(至少比起Perl的h2xs是要直观不少,这也是那时普遍认为tcl的胶水性比perl更强的原因之一),而且以DString类型提供了非常良好的中文支持,因此Tcl确实是嵌入、扩展开发的最理想语言之一,除了相较lua速度会较慢(这点对于高并发的游戏服务器领域比较敏感,所以Hipe erlang才显得如此重要)。下面我们就实际来编写一个简单的tcl扩展,作为编写tcl扩展快乐旅程的开始:

 

#######################

######## ex.c #########

#######################

 

#include <tcl.h>

 

static int
Hello_Cmd(ClientData cdata, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
    Tcl_SetObjResult(interp, Tcl_NewStringObj("Hello, World!", -1));
    return TCL_OK;
}


int DLLEXPORT
Ex_Init(Tcl_Interp *interp)
{
    if (Tcl_InitStubs(interp, TCL_VERSION, 0) == NULL) {
        return TCL_ERROR;
    }
    /* changed this to check for an error - GPS */
    if (Tcl_PkgProvide(interp, "Hello", "1.0") == TCL_ERROR) {
        return TCL_ERROR;
    }
    Tcl_CreateObjCommand(interp, "hello", Hello_Cmd, NULL, NULL);
    return TCL_OK;
}

 

至此我们创建了一个tcl解析器用于运行Hello_Cmd函数,并通过Tcl_SetObjResult设置该函数的返回值,然后通过Tcl_CreateObjCommand将Hello_Cmd注册给tcl,在tcl的世界中Hello_Cmd的名字叫hello,可通过调用hello命令(tcl中的函数称命令)来调用扩展中的Hello_Cmd函数。接下来我们用以下命令将上面的ex.c文件编译成动态库。

 

gcc -shared -o libex.so -DUSE_TCL_STUBS ex.c -I/usr/include/tcl8.6 -L/usr/lib -ltclstub8.6

 

不同机器的include和lib目录可能不同,请参考tclConfig.sh的内容,在我的Mandriva 2010 spring中它存在于/usr/lib/tclConfig.sh,成功后会在当前目录生成libex.so动态库。接下来我们来写一段使用这个扩展的tcl:

 

#######################

####### use.tcl #######

#######################

 

#!/usr/bin/tclsh

 

load ./libex

puts [hello]

 

运行一下tclsh use.tcl,如果你看到输出:Hello, World!,那么恭喜你成功完成了第一个tcl扩展的编写。很轻松而且很有趣不是么。

转载于:https://www.cnblogs.com/luolan/archive/2010/09/20/1831399.html

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
## 1 自定义命令 (1)编写自定义命令 > 1 编写自定义命令内容 > 2 注册指定命令 ```tcl /* *set up numbers sort command */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <tcl.h> // numbers sort int NumSort(ClientData ClientData, Tcl_Interp *Interp, int objc, Tcl_Obj *const objv[]) { double arr[objc], tmp; char *pstr, *pstr2; char buf[100]; int cnt = 1, cnt2 = 0, i = 0; //1. string convert number,numbers sort for(cnt = 1; cnt < objc; ++cnt) { //1.1 string convert number tmp = atof(Tcl_GetString(objv[cnt])); //1.2 numbers sort if(cnt == 1) arr[0] = tmp; else { for(cnt2 = cnt-1; cnt2 > 0; --cnt2) { if(tmp >= arr[cnt2 -1]) { arr[cnt2] = tmp; break; } else arr[cnt2] = arr[cnt2 -1]; } } } //2. numbers convert string and return for(cnt2 = 0; cnt2 < objc -1;++cnt2) { Tcl_AppendResult(Interp,gcvt(arr[cnt2], sizeof(arr[cnt2]), buf), " ",NULL); } return 0; } int Numsort_Init(Tcl_Interp *Interp) { //login command Tcl_CreateObjCommand (Interp, "numsort", NumSort, 0, 0); return TCL_OK; } ``` > 注解: (1)初始化函数Init的名字必须是文件名首字母大写+"_Init",上文c文件名是numsort.c, 故初始化函数名为Numsort_Init; ## 2 编译生成动态库 (1) 格式: gcc -fPIC -shared ____.c -o lib____.so ``` $ gcc -fPIC -shared numsort.c -o libnumsort.so ``` > 注解: (1) ____.c 代表要进行编译的C文件名 (2)lib___是lib+C文件名,生成动态库的库名为lib__.so ## 3 加载动态库 (1) 格式: load libname ```tcl % load libnumsort.so ``` ## 4 调用自定义命令 (1) commondname args ```tcl % numsort 1 1.1 2 2.2 22 3.3 90 2.5 11.11 1 1.1 2 2.2 2.5 3.3 11.11 22 90 ``` ## 1 自定义命令 (1)编写自定义命令 > 1 编写自定义命令内容 > 2 注册指定命令 ```tcl /* *set up numbers sort command */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <tcl.h> // numbers sort int NumSort(ClientData ClientData, Tcl_Interp *Interp, int objc, Tcl_Obj *const objv[]) { double arr[objc], tmp; char *pstr, *pstr2; char buf[100]; int cnt = 1, cnt2 = 0, i = 0; //1. string convert number,numbers sort for(cnt = 1; cnt < objc; ++cnt) { //1.1 string convert number tmp = atof(Tcl_GetString(objv[cnt])); //1.2 numbers sort if(cnt == 1) arr[0] = tmp; else { for(cnt2 = cnt-1; cnt2 > 0; --cnt2) { if(tmp >= arr[cnt2 -1]) { arr[cnt2] = tmp; break; } else arr[cnt2] = arr[cnt2 -1]; } } } //2. numbers convert string and return for(cnt2 = 0; cnt2 < objc -1;++cnt2) { Tcl_AppendResult(Interp,gcvt(arr[cnt2], sizeof(arr[cnt2]), buf), " ",NULL); } return 0; } int Numsort_Init(Tcl_Interp *Interp) { //login command Tcl_CreateObjCommand (Interp, "numsort", NumSort, 0, 0); return TCL_OK; } ``` > 注解: (1)初始化函数Init的名字必须是文件名首字母大写+"_Init",上文c文件名是numsort.c, 故初始化函数名为Numsort_Init; ## 2 编译生成动态库 (1) 格式: gcc -fPIC -shared ____.c -o lib____.so ``` $ gcc -fPIC -shared numsort.c -o libnumsort.so ``` > 注解: (1) ____.c 代表要进行编译的C文件名 (2)lib___是lib+C文件名,生成动态库的库名为lib__.so ## 3 加载动态库 (1) 格式: load libname ```tcl % load libnumsort.so ``` ## 4 调用自定义命令 (1) commondname args ```tcl % numsort 1 1.1 2 2.2 22 3.3 90 2.5 11.11 1 1.1 2 2.2 2.5 3.3 11.11 22 90 ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值