我想在C中重写一些关键函数以提高速度,我正在处理大量输入数据,因此效益可能很大。
在我的环境中,我没有C编译器,所以我无法在运行期间进行编译"做法。应编译C文件,并从编译文件中调用和执行函数。我怎么能这样做?
答案 0 :(得分:1)
您应该编写一些桥接函数并将其打包到可加载的扩展DLL中(或者适用于您的平台的任何正确的文件扩展名)。
合理的起点是sample extension。它的主要代码是generic/sample.c
(它只是一个SHA-1实现,普通的C代码是用旧式编写的)。将其桥接到Tcl的代码在generic/tclsample.c
中,由两个函数组成。
Sha1_Cmd
是在C中实现Tcl命令的代码。该名称是正式任意的,但类型签名不是。其中有趣的Tcl API函数是Tcl_GetIndexFromObj
,Tcl_GetString
(也有Tcl_GetStringFromObj
,参数略有不同),Tcl_GetIntFromObj
,Tcl_AppendResult
,{{1} }和Tcl_SetObjResult
。不同寻常的是,函数不会调用Tcl_NewIntObj
来处理用户传入错误数量的参数的情况。
命令实现的通常模式是首先解析参数,确定命令被要求执行的操作是否合理并且当事情不合理时返回错误(即,Tcl异常)。然后调用底层代码来实际执行真正的任务。最后,底层代码的结果 - 包括任何报告的失败 - 被转换回可以通过Tcl的形式。此模式非常常见。
Tcl_WrongNumArgs
是在load
DLL时将命令安装到Tcl中的代码。名称和签名都很重要;名称必须与计算的库名称匹配后缀Sample_Init
(在这种情况下,我们期望被称为_Init
或sample.dll
或类似的东西)。请注意,它会调用libsample.so
,Tcl_InitStubs
和Tcl_PkgProvide
。 Tcl_CreateObjCommand
(或其相关功能之一)也是合理的,但这个包不会这样做。
编译指令往往会在平台之间略有不同,但如果您曾经在一个系统上构建了一个扩展DLL,那么其他系统实际上并没有那么不同。
将DLL转换为完整包然后需要在它旁边添加一点Tcl_SetVar
,并且安装包会将这两个文件转储到正确的目录中(如果你正在做的话,可能正确设置权限)系统安装等)。你可以得到比这更复杂的东西,但这并不难。对于特定于应用程序的内容,您可以将DLL / package-index文件保存在您控制的目录中,并在执行pkgIndex.tcl
之前扩展Tcl的auto_path
全局变量。