想要从共享对象文件创建模块x.so
以避免load
命令。共享对象 C 源代码x.c
定义包p
,其中包含版本1
。
我将x.so
重命名为p-1.tm
并在::tcl::tm::path
和 二手package require p 1
它显示无法读取命令的错误。这是因为主文件x.so
而不是x.tcl
。
模块始终source
d. 使它们也包含一个可加载的库需要一些技巧。这是一种方法。像这样制作一个 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
,以便我们清理掉所有文件名操作机器整齐地清理掉。
使用虚拟文件系统的更复杂的方法是可能的,但需要更多的代码来解释。他们仍然只是在做这种事情,但更多的诡计隐藏在视线之外。