2013-04-24 43 views
0

在我的公司,我们目前使用的是Tcl 8.4,我们希望更新到8.6。我们希望这样做的方式是将所有新的C++扩展编写为与8.6和8.4兼容,以便所有新扩展都可以在我们的旧测试人员上工作,由于兼容性问题,我们无法将其更新到8.4。编写一个Tcl扩展,可用于多个版本的Tcl

有没有办法编写代码或配置VS 2012,以便DLL会检测到Tcl的版本并加载它需要的动态库?

如果我使用茶壶扩展架构,我会达到相同的结果吗?

+0

如果使用存根机制,这不应该是必需的。 – 2013-04-24 21:31:55

+0

@JohannesKuhn也许我没有正确实施存根。目前,我正在VS项目设置下的“C++预处理器定义”下定义'USE_TCL_STUBS',并在VS项目设置中包含'tclstub84.lib',在“连接器输入附加依赖项”下。有没有什么办法可以通过编程方式而不是通过项目设置来实现? – Chrono 2013-04-24 21:45:13

+0

您是否尝试用Tcl 8.6“加载”您的.dll文件(使用8.4编译)? – 2013-04-24 22:12:54

回答

3

我从评论中看到,您已经知道如何构建使用存根机制的库。

存根机制的设计是这样一种方式,你可以使用load带来了DLL和Tcl的任何版本是A 与版本的Tcl该DLL建我兼容工作反对。 TCL还具有是不是意味着以后版本具有相同主要版本(在“8.4”中的“8”)数与早期版本兼容的 pplication inary 兼容性覆盖整个院落规则。

反之亦然。 8.4与ABI不兼容8.6,或者至少我们不承诺它是。即使撇开这个事实,即有额外的A P我在8.6中的函数不在8.5或8.4中,用于特定函数的存根表中的确切时隙可能已经移动(自动生成的C宏管理转发API兼容性,但这些不兼容反向兼容性)。您应该总是根据您希望支持的最早版本的Tcl API和存根库构建扩展DLL。 (我知道有几个人谁没有的;他们的代码是非常复杂的,而不是在所有推荐的方法。)

但是...

那是不是你可以采取的唯一方法。您也可以针对您希望支持的每个版本的Tcl构建库,从而生成许多不同名称的DLL,可能为mylib84.dll,mylib85.dllmylib86.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的单一下载,以便您可以提供一组直接指令而不需要大量平台相关位?你可以使用软件包来实现,而且成本只是一些构建的复杂性,一些带宽和一些磁盘空间......

+0

这是人们在评论中告诉你的扩展版本,如果你在使用存根时遇到问题,可能的(如果不是非常愉快的)解决方法。 – 2013-04-25 14:57:45

+0

这是一个非常有趣的答案,当你用这种方式打包它时,它只会产生1个.dll文件,还是我将不得不在维护多个.dll文件后? – Chrono 2013-04-25 17:30:10

+1

你仍然有多个DLL,但你会把它们放在同一个地方(名字略有不同),所以在构建后管理它们不会太难。然后,您可以将它们全部打包成一个starkit,这将得到ActiveTcl的支持,并且将是一个单一文件解决方案。那么,单一文件一旦建成(将包含多个DLL,但无论如何)。 – 2013-04-25 19:22:06