要从共享对象文件x.so
创建模块,以避免使用load
命令。共享库C源代码x.c
定义了版本为p
的软件包1
。
我将x.so
重命名为p-1.tm
,并在::tcl::tm::path
中添加了它的路径,
已使用package require p 1
它显示无法读取命令的错误。这是因为主文件是x.so
而不是x.tcl
。
答案 0 :(得分:2)
模块总是 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中 all 个动态库的加载都是通过load
进行的;这是唯一知道该怎么做的命令。我们正在为此做准备(默认情况下,实际文件是必需的,因为我们将实际加载委托给完成该工作的操作系统库调用; file tempfile
非常适合此工作!)。最后,我们将所有内容最后包装在apply
和tailcall load
中,以便我们清理干净地清理掉所有文件名处理机制。
使用虚拟文件系统的更复杂的方法是可能的,但是需要更多的代码来解释。他们仍然在做这种事情,但是看不到更多的诡计。