I am extending my Itcl program with C++ code and I got the following problem.
I want to return an "reference" in my Itcl code to an object in my C++ code using the TCL-C API, The return value should be registerd to an object in my Itcl code so after this I could invoke it methods. My problem is that I don't really know how to do this from both sides.
I saw that with TCL_LINKVAR(...) API function I can create an link between this objects to an string in TCL but I don't really understand how to use this TCL_LINKVAR function when it comes to objects and not to primitive types such as int,double,etc...
I will give a small example: This is my C++ code:
Tcl-C API code
#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 code
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++
}
...
}