首页 > 解决方案 > 我们可以通过将共享对象(即“*.so”文件)重命名为“$modulename-$version.tm”来创建模块吗?

问题描述

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

我重命名x.sop-1.tm添加了它的路径::tcl::tm::path并使用package require p 1

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

标签: 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非常适合这项工作!)。最后,我们将所有内容都包装在一个applyandtailcall load最后让我们清理掉所有的文件名操作机器被整齐地清理掉。

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


推荐阅读