首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在C++对象和itcl对象之间进行链接

如何在C++对象和itcl对象之间进行链接
EN

Stack Overflow用户
提问于 2018-08-26 09:55:03
回答 1查看 214关注 0票数 0

我正在用C++代码扩展我的Itcl程序,我遇到了以下问题。

我希望使用TCL在我的C++代码中将Itcl代码中的一个“引用”返回给一个对象,返回值应该注册到我的Itcl代码中的一个对象,这样之后我就可以调用它的方法了。我的问题是,我真的不知道如何从双方做到这一点。

我看到了TCL_LINKVAR(.)API函数--我可以在这个对象之间创建一个连接到TCL中的字符串,但是当涉及到对象时,我并不真正理解如何使用这个TCL_LINKVAR函数,而不是对诸如int、double等基本类型.

我将举一个小例子:这是我的C++代码:

Tcl-C API代码

代码语言:javascript
复制
#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代码

代码语言:javascript
复制
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++
    }
...
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 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,至少从外部看,和我上面描述的非常相似。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52025095

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档