Я расширяю свою программу Itcl с помощью кода C ++, и у меня возникла следующая проблема:
Я хочу вернуть "ссылку" в моем коде Itcl на объект в моем коде C ++ с использованием API TCL-C, Возвращаемое значение должно быть зарегистрировано для объекта в моем коде Itcl, чтобы после этого я мог вызывать его методы.Моя проблема в том, что я не знаю, как это сделать с обеих сторон.
Я видел, что с помощью API-функции TCL_LINKVAR (...) я могу создать ссылку между этими объектами на строку в TCL, но я не совсем понимаю, как использовать эту функцию TCL_LINKVAR, когда дело касается объектов ине для примитивных типов, таких как int, double и т.д ...
Я приведу небольшой пример: Это мой код C ++:
Код API Tcl-C
#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++
}
...
}