如何在C++代码上使用 Tcl-C API

how to use Tcl-C API on C++ code

本文关键字:Tcl-C API 代码 C++      更新时间:2023-10-16

我目前正在学习如何使用 Tcl-C api,我正在阅读"Tcl 和 Tk 中的实用编程 - 第四版",但我发现很难理解当我有一个程序时 API 的实际工作方式C++我想使用此 API 执行包装函数,这将为我提供一个将由我的脚本加载的共享对象。

我会尽量说得更清楚。
假设我有以下C++文件:

/* example.h */
Class A {
private:
std::vector<int> data;
public:
A(){}
}

和 C 包装器文件:

/* match.c */
#include <tcl.h>
#include "example.h"
// should create an instance of an A object for future use.
int Tcl_ACmd (clientData, interp, argc, argv)
// should take an instance of an A object that was created and return it's data vector.
int Tcl_AGetDataCmd(clientData, interp, argc, argv)
int Match_Init(Tcl_Interp *interp)
{  
if (NULL == Tcl_InitStubs (interp, TCL_VERSION, 0)) {
return TCL_ERROR;
}
Tcl_CreateCommand (interp, "A", Tcl_MaxCmd, (ClientData)NULL,(void (*)())NULL);
Tcl_CreateCommand (interp, "get", Tcl_MaxCmd, (ClientData)client_data,(void (*)())NULL);  
return Tcl_PkgProvide(interp, "Match", "1.0");
}

最后是剧本:

# script.tcl
$> load match.o
$> A   (This will create an A instance)
$> A get   (this will return the data of A)

现在,我明白了当我调用 AGetData 命令时,ClientData 实际上是 void* 类型,应该强制转换为 A 类。但我仍然不明白如何将参数传递给包装函数(我应该用 Tcl_Obj 更改 argv 吗?(以及在哪里创建对象以及如何跟踪它们以稍后通过脚本调用那里的方法。

与其尝试从 C 调用C++代码(由于 C++ 的名称重整,这总是一个问题(,不如创建C++代码来调用 C 例程。 somename_Init程序 并且 somenameCmd 过程需要在C++代码中声明为"外部 "C" 以便 Tcl 可以在加载共享库时找到它们。

我将从一个工作示例开始:

具有毫秒精度的文件上次修改时间在 C 中有一个完整的示例。

然后进行修改以使其可编译并可与C++一起使用。

然后进行更改以使用所需的名称,并进行更改以支持您的C++类。

还有一个C++的例子:https://wiki.tcl-lang.org/21007

它似乎为它创建的每个对象创建了一个新的 Tcl 命令。 这是一种可能的解决方案。

另一种可能性是将每个新对象添加到命名空间集合中。

或者将保存在新数据结构中的C++对象句柄保留在新的 Tcl 命令,并通过某种索引访问它们。

另一种可能性是实际创建一个 Tcl 对象句柄 每个对象。 这相当复杂。

这完全取决于您的用例要求。 当然,单例对象要简单得多。