Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

calling "c" from TCL

42 views
Skip to first unread message

Pablo

unread,
Feb 5, 2012, 3:42:30 PM2/5/12
to
Hello,

To sum vectors i wrote a code like this; it is receiving 3 vectors
data1, data2, data3. The diference between data1 and data2 is returned
with Tcl_SetObjResult, but i would like modify data3, how can i modify
data3??

Thanks

#include <tcl.h>
#include <iostream>
using namespace std;


int obj_vecsub(ClientData clientData, Tcl_Interp *interp, int argc,
Tcl_Obj *const objv[]);
int obj_vecsub(ClientData clientData, Tcl_Interp *interp, int argc,
Tcl_Obj *const objv[])

{
if (argc != 3) {
Tcl_WrongNumArgs(interp, 1, objv, (char *)"?x? ?y?");
return TCL_ERROR;
}
int num1=0, num2=0, num3=0;
Tcl_Obj **data1, **data2, **data3;
if (Tcl_ListObjGetElements(interp, objv[1], &num1, &data1) !=
TCL_OK)
return TCL_ERROR;
if (Tcl_ListObjGetElements(interp, objv[2], &num2, &data2) !=
TCL_OK)
return TCL_ERROR;
if (Tcl_ListObjGetElements(interp, objv[3], &num2, &data3) !=
TCL_OK)
return TCL_ERROR;

if (num1 != num2) {
Tcl_SetResult(interp, (char *)"vecsub: two vectors don't have the
same size", TCL_STATIC);
return TCL_ERROR;
}

Tcl_Obj *tcl_result = Tcl_NewListObj(0, NULL);
Tcl_Obj *tcl_dummy = Tcl_NewListObj(0, NULL);
for (int i=0; i<num1; i++) {
double d1=0, d2=0, d3=77;
if (Tcl_GetDoubleFromObj(interp, data1[i], &d1) != TCL_OK) {
Tcl_SetResult(interp, (char *)"vecsub: non-numeric in first
argument", TCL_STATIC);
return TCL_ERROR;
}
if (Tcl_GetDoubleFromObj(interp, data2[i], &d2) != TCL_OK) {
Tcl_SetResult(interp, (char *)"vecsub: non-numeric in second
argument", TCL_STATIC);
return TCL_ERROR;
}
Tcl_ListObjAppendElement(interp, tcl_result, Tcl_NewDoubleObj(d1-
d2));
Tcl_ListObjAppendElement(interp, tcl_dummy,
Tcl_NewDoubleObj(d3));
}
Tcl_SetObjResult(interp, tcl_result);
return TCL_OK;
}

//int AddObjCmd(ClientData clientData, Tcl_Interp *interp,int objc,
Tcl_Obj *CONST objv[]);

extern "C" {
int Add_Init(Tcl_Interp *interp) ;
} // end extern "C" *

int Add_Init(Tcl_Interp *interp) {
/* Register the Add command */
Tcl_CreateObjCommand(interp, "vecsub", obj_vecsub,(ClientData) NULL,
(Tcl_CmdDeleteProc *) NULL);

/* Declare the package */
Tcl_PkgProvide(interp, "vecsub", "1.1");
return TCL_OK;
}

Alexandre Ferrieux

unread,
Feb 5, 2012, 6:47:09 PM2/5/12
to
On Feb 5, 9:42 pm, Pablo <pablodecasti...@gmail.com> wrote:
> Hello,
>
> To sum vectors i wrote a code like this; it is receiving 3 vectors
> data1, data2, data3. The diference between data1 and data2 is returned
> with Tcl_SetObjResult, but i would like modify data3, how can i modify
> data3??

Let the script level do that; just return the value:

set data3 [vecsub $data1 $data2]

Unless you have strong reasons (like modifying more than one var),
there's no point in bringing to the C level the equivalent of [upvar].

-Alex

Pablo

unread,
Feb 6, 2012, 4:16:57 AM2/6/12
to
On 6 feb, 00:47, Alexandre Ferrieux <alexandre.ferri...@gmail.com>
wrote:
Thanks Alex, but the idea is modify more than one var, the script is
working like;

set result [vecsub $dat1 $dat2 $dat3], and i would like modify $result
(it is doing calling the procedure) and $dat3

Thanks

Aric Bills

unread,
Feb 6, 2012, 11:16:48 AM2/6/12
to
If you want to modify a variable, you need to pass its name (rather
than its value) to your command. So, if you want to modify dat3, you'd
call your command like this:

set result [vecsub $dat1 $dat2 dat3]

If you need to get the value of the variable with that name, use
Tcl_ObjGetVar2. To set the variable, use Tcl_ObjSetVar2.

Alexandre Ferrieux

unread,
Feb 6, 2012, 3:40:44 PM2/6/12
to
You're not making it immediately obvious how this would modify several
variables...
Assuming you do it right (passing dat3 instead of $dat3, and
[upvar]ring it within the C function), what separate thing would the
function result hold ?

-Alex

Pablo

unread,
Feb 7, 2012, 3:49:21 AM2/7/12
to
Hi Aric,

I understand that "C" function transform dat3 in a variable for tcl,
is it?

Pablo

unread,
Feb 7, 2012, 4:43:47 AM2/7/12
to
Thanks Aric,

Your point is working perfectly, just adding to "c" function;
Tcl_ObjSetVar2( interp, objv[3], NULL, tcl_dummy, TCL_LEAVE_ERR_MSG );
and calling the script :
set c [vecsub $a $b d]

it is giving me $c and $d with modify values
Message has been deleted

Emiliano

unread,
Feb 7, 2012, 11:23:59 AM2/7/12
to
Two things worth noting:

1) You can return *two* vectors (list of lists) and use

lassign [vecsub $a $b] c d

and avoid accessing the variable from the C side.

2) your code is leaky; more specifically, you are not managing
Tcl_Obj's
reference count properly. Consider what happens with both tcl_result
and
tcl_dummy variables if Tcl_GetDoubleFromObj() fails.
See http://wiki.tcl.tk/1192 and http://wiki.tcl.tk/14880 for a
discussion
on this subject.

Regards
Emiliano

Pablo

unread,
Feb 8, 2012, 11:43:31 AM2/8/12
to
> Seehttp://wiki.tcl.tk/1192andhttp://wiki.tcl.tk/14880for a
> discussion
> on this subject.
>
> Regards
> Emiliano

Thanks Emiliano,

your point 1) is very useful.

Pablo
0 new messages