我们可以通过将其重命名为"$modulename-$version.tm"来从共享对象(即'*.so'文件)创建模块吗?



想要从共享对象文件创建模块x.so以避免load命令。共享对象 C 源代码x.c定义包p,其中包含版本1

我将x.so重命名为p-1.tm并在::tcl::tm::path和 二手package require p 1

它显示无法读取命令的错误。这是因为主文件x.so而不是x.tcl

模块始终sourced. 使它们也包含一个可加载的库需要一些技巧。这是一种方法。像这样制作一个 Tcl 脚本:

apply {{scriptname realname} {
set script [open $scriptname]
chan configure $script -eofchar x1a
chan read $script
chan configure $script -translation binary
chan seek $script 1 current; # Reset EOF state and skip past the EOF character
set f [file tempfile filename $realname.so]
chan copy $script $f
chan close $f
chan close $script
tailcall load $filename $realname; # Used to find the _Init function
}} [info script] YourRealLibraryName

用ASCII EOF 字符 (Ctrl+Z) 连接它,然后在最后连接您的真实共享库,将其全部保存为模块文件。当脚本被源化时,它会将库从自身的末端复制到一个临时文件中,并从中加载它。


这取决于这样一个事实,即source始终将其用于读取脚本的通道配置为使用 EOF 字符充当文件结束标记,即使在通常不使用它的系统上也是如此。然后,您可以阅读过去并从中提取所需的任何有效负载数据。在末端连接可加载库是微不足道的,但它需要在其他地方提取才能实际输入load。在内部,Tcl中动态库的所有加载都要经过load;这是唯一知道如何执行此操作的命令。我们只是在为它准备方式(默认情况下需要真实文件,因为我们将实际加载委托给完成这项工作的操作系统库调用;file tempfile非常适合这项工作!最后,我们将所有内容包装在一个apply中,最后tailcall load,以便我们清理掉所有文件名操作机器整齐地清理掉。

使用虚拟文件系统的更复杂的方法是可能的,但需要更多的代码来解释。他们仍然只是在做这种事情,但更多的诡计隐藏在视线之外。

最新更新