Tcl中的load命令

tcl中的load命令还是很神奇的。在这里翻译一下tcl的load文档,学习一下。

名字

load - 加载机器代码,初始化新的命令

概要

load filename

load filename packagename

load filename packagename interp

描述

这个命令把一个文件中的二进制代码加载到应用的地址空间,然后调用package中的初始化程序把这些代码集成到解释器中。filename是包含二进制代码的文件名。它具体的形式在不同的系统上面会有所不同,但是在大部分系统上,它就是一个共享库,比如Solaris上面的.so文件,Windows上面的DLL文件。packagename就是包的名字,被用来计算初始化程序的名字。interp是我们要集成二进制代码的解释器的名字。如果interp忽略,那么就指向调用load的那个解释器。

一旦文件被加载到应用的地址空间,两个初始化程序中的一个就会被新的代码调用。典型的是,初始化程序会添加新的命令到Tcl解释器当中。初始化程序的名字由packagename确定。对于一般的解释器,初始化程序会有pkg_Init这样的形式,pkg就是packagename(其中第一个字母大写,剩下的字母小写)。比如,如果packagename是foo或者FOo,那么初始化进程就是Foo.Init。

如果目标解释器是一个安全的解释器,那么初始化程序就是pkg_SafeInit。pkg_SafeInit要小心的写,这样的话,它才能用不被信任的代码写的package中的部分代码来初始化安全解释器。更多的关于Safe-Tcl的信息,请参考safe手册。

初始化程序必须有如下的原型:

typedef int Tcl_PackageInitProc(Tcl_Interp *interp);

interp指向这个包要加载的解释器。初始化程序必须返回TCL_OK或者TCL_ERROR来表明是否成功的进行了初始化。如果失败了,还要设定解释器的结果到一个错误信息。load命令的结果就是初始化程序的结果。

实际的加载一个文件,在一个应用中只会被加载一次。如果一个filename被加载到多个解释器当中,那么第一次load会加载代码调用初始化程序,后面的load会调用初始化程序,但是不会再加载一次代码了。卸载或者重新加载一个包是不可能的。

如果通过调用Tcl_StaticPackage程序注册的静态连接包,load也支持。如果filename是一个空串,那么packagename必须要有。

如果packagename忽略或者是一个空串,Tcl会猜测package的名字。这可能在不同的系统中有不同的表现。大部分UNIX平台上面用的默认的猜测是用filename中最后的元素,如果是lib开头,就剔除这三个字符,然后使用剩下的字母或者下划线。比如命令load libxyz4.2.so会使用package名xyz,而命令load bin/last.so {}会使用package名last。

如果filename是一个空串,那么packagename就必须指定。load会通过packagename在已经加载的包(通过Tcl_StaticPackage程序注册过的)中进行搜索,如果找到就使用。否则,就用packagename在动态加载包中进行搜索,如果已经找到就使用它。如果不同的文件加载了不同版本的包,那就选择最先加载的包。

兼容性问题

Windows

当一个加载失败,并报“library not found”错误,也有可能是有一个依赖库没有找到。要看依赖库,在DOS console下面输入,“dumpin -imports <dllname>”来看哪些库必须要先加载。当在当前目录下面加载一个DLL的时候,Windows会忽略“./”,然后用启发式搜索代替。要避免这种情况,用如下命令加载DLL:

load [file join [pwd] mylib.DLL]

BUGS

如果相同的文件用不同的文件名进行加载,这会在进程的地址空间加载多次。然后行为上随着不同的系统而不同(有些系统会检测到冗余的加载,有些不会)。

例子

以下是一个最小拓展:

#include <tcl.h>
#include <stdio.h>
static int fooCmd(ClientData clientData,
        Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) {
    printf("called with %d arguments\n", objc);
    return TCL_OK;
}
int Foo_Init(Tcl_Interp *interp) {
    if (Tcl_InitStubs(interp, "8.1", 0) == NULL) {
	return TCL_ERROR;
    }
    printf("creating foo command");
    Tcl_CreateObjCommand(interp, "foo", fooCmd, NULL, NULL);
    return TCL_OK;
}

当用一个合适的名字将上面的程序创建为共享库之后,它就可以被加载到Tcl当中了。

# Load the extension
switch $tcl_platform(platform) {
   windows {
      load [file join [pwd] foo.dll]
   }
   unix {
      load [file join [pwd] libfoo[info sharedlibextension]]
   }
}

# Now execute the command defined by the extension
foo

参考

info sharedlibextension, Tcl_StaticPackage, safe

关键词

binary code, loading, safe interpreter,shard library

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值