在我的公司,我们目前正在使用Tcl 8.4,我们希望更新到8.6。我们想要这样做的方法是编写所有新的C ++扩展以与8.6和8.4兼容,这样所有新的扩展都可以在我们的老测试人员上工作,因为兼容性问题我们无法更新到8.4。
有没有办法编写代码或配置VS 2012,以便dll检测Tcl的版本并动态加载它需要的库?
如果我使用茶壶扩展架构,我会得到相同的结果吗?
答案 0 :(得分:3)
我从评论中看到你已经知道如何构建使用存根机制的库。
存根机制旨在以这样的方式工作,即您可以使用load
将DLL带入任何版本的Tcl,即 B 我兼容构建DLL的Tcl版本。 Tcl还具有 A pplication B inary I 接口兼容性规则,这意味着以后的版本具有相同的主要版本号(“8.4”中的“8”)与早期版本兼容。
反之则不然。 8.4与8.6不兼容ABI,或者至少我们不承诺它。即使不考虑8.6中存在额外的A P I函数,但是在8.5或8.4中,函数存根表中的确切插槽用于特定功能可能已移动(自动生成的C宏管理正向API兼容性,但那些不能应对反向兼容性)。您应始终针对您希望支持的最旧版本的Tcl API和存根库构建扩展DLL。 (我知道有些人不这样做;他们的代码非常复杂,根本没有被推荐作为一种方法。)
<强>然而... 强>
这不是你可以采取的唯一方法。您还可以针对您希望支持的每个Tcl版本构建库,从而生成许多您提供不同名称的DLL,可能是mylib84.dll
,mylib85.dll
和mylib86.dll
。然后,将这些组合在一起组成一个Tcl包以及一个知道如何加载正确的pkgIndex.tcl
,可能是这样的:
if {[package vsatisfies [info tclversion] 8.6]} {
package ifneeded MyLib 1.0 [list load [file join $dir mylib86.dll]]
} elseif {[package vsatisfies [info tclversion] 8.5]} {
package ifneeded MyLib 1.0 [list load [file join $dir mylib85.dll]]
} elseif {[package vsatisfies [info tclversion] 8.4]} {
package ifneeded MyLib 1.0 [list load [file join $dir mylib84.dll]]
}
使用此方案,您甚至可以使8.5和8.4的版本不支持存根(如果在您的情况下这是有意义的)。唯一的缺点是你的构建过程现在变得更加复杂:你必须构建三个版本的库而不是一个版本。
通过将代码放入包中并隐藏该包中正在进行的操作的详细信息,您可以执行非常复杂的操作。例如,可以使用此机制的变体来构建支持多种体系结构的单个可再发行组件包;单个下载,支持32位Windows,64位Windows和各种版本的Linux,以便您可以提供一组直接指令,而不需要很多依赖于平台的位?你可以用软件包来做,而成本只是一些构建复杂性,一些带宽和一些磁盘空间......