我正在用C++代码扩展我的Itcl程序,我遇到了以下问题。
我希望使用TCL在我的C++代码中将Itcl代码中的一个“引用”返回给一个对象,返回值应该注册到我的Itcl代码中的一个对象,这样之后我就可以调用它的方法了。我的问题是,我真的不知道如何从双方做到这一点。
我看到了TCL_LINKVAR(.)API函数--我可以在这个对象之间创建一个连接到TCL中的字符串,但是当涉及到对象时,我并不真正理解如何使用这个TCL_LINKVAR函数,而不是对诸如int、double等基本类型.
我将举一个小例子:这是我的C++代码:
Tcl-C API代码
#include <tcl.h>
#include "classA.h"
class MyObject {
int id;
ClassA * a; // classA is defined somewhere else
public:
MyObject(int iid) : id(iid) {}
void returnA() { return a; }
};
extern "C" int do_something_command(ClientData clientData,
Tcl_Interp* interp,
int objc,
Tcl_Obj* const objv[])
{
if (objc < 2) {
Tcl_WrongNumArgs(interp, 1, objv, "method ?argument ...?");
return TCL_ERROR;
}
MyObject* p = (MyObject*)clientData;
classA * ret_val = p->returnA();
if (LINK_VAR.... != TCL_OK) { // here should be a linkage between ret_val to an Itcl object
return TCL_ERROR;
}
return TCL_OK;
}
extern "C" int test_create(ClientData clientData,
Tcl_Interp* interp,
int objc,
Tcl_Obj* const objv[])
{
static int obj_count = 0;
MyObject* p = new MyObject(obj_count);
char obj_name[13 + TCL_INTEGER_SPACE];
sprintf(obj_name, "::testobj%d", obj_count++);
Tcl_CreateObjCommand(interp, "cDoSomething",
(Tcl_ObjCmdProc*)do_something_command,
(ClientData) p, (Tcl_CmdDeleteProc *) NULL);
Tcl_SetObjResult(interp, Tcl_NewStringObj(obj_name, strlen(obj_name)));
return TCL_OK;
}
extern "C" DLLEXPORT int Test_Init(Tcl_Interp *interp)
{
if (Tcl_InitStubs(interp, TCL_VERSION, 0) == NULL) {
return TCL_ERROR;
}
if (Tcl_PkgRequire(interp, "Tcl", TCL_VERSION, 0) == NULL) {
return TCL_ERROR;
}
if (Tcl_PkgProvide(interp, "test", "0.1") != TCL_OK) {
return TCL_ERROR;
}
Tcl_CreateObjCommand(interp, "test::create",
(Tcl_ObjCmdProc*)test_create,
(ClientData)NULL, (Tcl_CmdDeleteProc*)NULL);
return TCL_OK;
}Itcl代码
load test.o // this will be the name of .o file I will create from my C++ code
itcl::class A {
...
public method doSomething {}
... }
itcl::class B {
constructor {} {
set temp [test::create]
set a [$temp cDoSomething] // should register a as an classA object
// here I will call methods that are related to classA object that are registered in C++
}
...
}发布于 2018-08-27 14:06:52
首先,简单C类型(只有数字和char* (其中Tcl管理char*的内存分配)和Tcl变量之间的变量链接映射;它并不适合您所做的事情。原则上,您可以对任何结构进行同样的操作;链接代码是基本的Tcl变量跟踪原语API的包装器。它并不适合于任何不透明类型或任何具有动态生命周期的东西。
最简单的技术是将映射(例如std::map<std::string,MyObject*>)保存在C++端,这样就可以进行按名查找操作。一旦您得到了它,您就可以发明一种简单的命名机制,并将字符串名称保存在Itcl对象中的Tcl变量中。C++端的方法由命令代理,这些命令将名称作为参数之一,查找相关对象,并传递其余的参数(使用您喜欢的任何附加解析/类型转换),而Itcl方法是简单的包装器,它们在正确的位置传递附加的名称/句柄(析构函数是相同的,只不过是代理从-from-map和delete中删除)。有其他方法可以做到这一点,但我刚才描述的方法很容易实现,并且可以首先尝试;它可以让您在设计级别无需付出很大的努力就可以原型API。请注意,对象的字段不是以这种方式很好地映射的;它只用于方法,而在C++中什么才是好的API与Tcl/Itcl中的好API肯定不一样。
您可以通过使用SWIG生成绑定来实现类似的目标。它在内部所做的事情并没有太大的不同,但它将绑定更多地放在C++中,而不是放在Tcl方面。Itcl包装的工作方式与…略有不同。
如果您使用的是Itcl 4,则可以使用C++ API ( Itcl 4构建在此基础上)从TclOO进行方法绑定。TclOO包括用于定义自定义方法和直接将C和C++对象附加到其实例的机制;这可以使绑定更加复杂(并允许您在things的Tcl端执行子类之类的操作),但由于这一点,它要复杂一些。你最终会看到的API,至少从外部看,和我上面描述的非常相似。
https://stackoverflow.com/questions/52025095
复制相似问题