Tcl 中的包严格来说是一个高级概念,它从功能包的实现方式中抽象出来。当你说 package require foo 时,包管理器会离开并查看如何实际获取包,并提供给你。
那么它们是如何实现的呢?核心思想是有一个特定格式的索引文件,它描述了一堆要做的事情,通常使用source 来获取脚本和load 来获取DLL。包实际使用哪个?取决于包装。 (也有一些方法可以在完全没有索引文件的情况下完成一个包,但是 Tcl 模块在其他方面是一个相当复杂的主题。)
但如果你实际上只有 DLL,你可以直接load 它。执行此操作时使用文件的绝对路径名;由于历史原因,没有目录分隔符的名称的工作方式不同(它们调用系统库发现机制,如果您知道它是哪个文件,则不需要该机制)。
# Any form that Tcl understands filenames in will do; I use / because it isn't a quote char
load C:/the/path/to/the/library.dll
这就是您真正需要做的所有事情。使用其索引文件正确安装包的唯一优点是使您的脚本可移植到具有不同安装位置的某个地方(并让您有机会描述包版本控制要求)。这很方便,但对于您自己做的事情并不重要。
那么,它是如何到达那里的呢?好吧,Tcl 实际上并不太在意。只要 DLL 包含正确的入口点函数(名称取决于 dll 名称;对于frobnicate.dll,它将查找Frobnicate_Init;这是可覆盖的)它就可以工作。制作它们的常用语言是 C 和 C++,但任何可以制作正确功能的语言都可以使用。对于需要复杂运行时才能运行的语言来说,这有点困难,但这取决于您。
有一些工具可以从 Tcl 代码生成 DLL,但它们通常不是为了方便提取代码,要么是因为它们是故意混淆器,要么是因为(在一种情况下,我工作)他们正在将 Tcl 代码转换为机器代码;没有可提取的来源。另一方面,有一些方法可以打包代码,使其只包含在一个 DLL 中,所以也许这就是这里发生的事情。真正提取你所能做的就是将代码弹出到一个工具中,从二进制代码中提取字符串(Unix strings 实用程序非常适合这个),看看是否有类似的东西;可能没有,但你可能会很幸运。
反汇编一个相当随意的 DLL 会令人不快。如果它是一个启用了 Tcl Stubs 的 DLL,这将特别烦人,因为它用通过 API 引用处理程序的间接调用替换了对 Tcl 的 API 的调用(在反汇编时很有用!),看起来真的在反汇编级别令人困惑。
如果您真的问这个问题是因为您正在考虑如何打包自己的代码以使用户不会将其分开,那么有一个商业工具(来自 ActiveState 的 TclDevKit)可以做得不错它。除了最坚定的人之外,它足以击败所有人。我自己不使用它,因为我不分发混淆代码,但我知道很多其他人推荐它。