f



calling "c" from TCL

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;
}
0
2/5/2012 8:42:30 PM
comp.lang.tcl 23428 articles. 2 followers. Post Follow

9 Replies
698 Views

Similar Articles

[PageSpeed] 14

On Feb 5, 9:42=A0pm, 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
0
2/5/2012 11:47:09 PM
On 6 feb, 00:47, Alexandre Ferrieux <alexandre.ferri...@gmail.com>
wrote:
> On Feb 5, 9:42=A0pm, 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:
>
> =A0 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

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
0
2/6/2012 9:16:57 AM
On Feb 6, 2:16=A0am, Pablo <pablodecasti...@gmail.com> wrote:
> On 6 feb, 00:47, Alexandre Ferrieux <alexandre.ferri...@gmail.com>
> wrote:
>
>
>
>
>
>
>
>
>
> > On Feb 5, 9:42=A0pm, 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 returne=
d
> > > with Tcl_SetObjResult, but i would like modify data3, how can i modif=
y
> > > data3??
>
> > Let the script level do that; just return the value:
>
> > =A0 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
>
> 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

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.
0
aric.bills (466)
2/6/2012 4:16:48 PM
On Feb 6, 10:16=A0am, Pablo <pablodecasti...@gmail.com> wrote:
> On 6 feb, 00:47, Alexandre Ferrieux <alexandre.ferri...@gmail.com>
> wrote:
>
>
>
>
>
>
>
>
>
> > On Feb 5, 9:42=A0pm, 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 returne=
d
> > > with Tcl_SetObjResult, but i would like modify data3, how can i modif=
y
> > > data3??
>
> > Let the script level do that; just return the value:
>
> > =A0 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
>
> 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

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
0
2/6/2012 8:40:44 PM
On 6 feb, 17:16, Aric Bills <aric.bi...@gmail.com> wrote:
> On Feb 6, 2:16=A0am, Pablo <pablodecasti...@gmail.com> wrote:
>
>
>
>
>
>
>
>
>
> > On 6 feb, 00:47, Alexandre Ferrieux <alexandre.ferri...@gmail.com>
> > wrote:
>
> > > On Feb 5, 9:42=A0pm, 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 retur=
ned
> > > > with Tcl_SetObjResult, but i would like modify data3, how can i mod=
ify
> > > > data3??
>
> > > Let the script level do that; just return the value:
>
> > > =A0 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
>
> > 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
>
> 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:
>
> =A0 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.

Hi Aric,

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

0
2/7/2012 8:49:21 AM
On 7 feb, 09:49, Pablo <pablodecasti...@gmail.com> wrote:
> On 6 feb, 17:16, Aric Bills <aric.bi...@gmail.com> wrote:
>
>
>
>
>
>
>
>
>
> > On Feb 6, 2:16=A0am, Pablo <pablodecasti...@gmail.com> wrote:
>
> > > On 6 feb, 00:47, Alexandre Ferrieux <alexandre.ferri...@gmail.com>
> > > wrote:
>
> > > > On Feb 5, 9:42=A0pm, Pablo <pablodecasti...@gmail.com> wrote:
>
> > > > > Hello,
>
> > > > > To sum vectors i wrote a code like this; it is receiving 3 vector=
s
> > > > > data1, data2, data3. The diference between data1 and data2 is ret=
urned
> > > > > with Tcl_SetObjResult, but i would like modify data3, how can i m=
odify
> > > > > data3??
>
> > > > Let the script level do that; just return the value:
>
> > > > =A0 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 [upva=
r].
>
> > > > -Alex
>
> > > 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 $resul=
t
> > > (it is doing calling the procedure) and $dat3
>
> > > Thanks
>
> > 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:
>
> > =A0 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.
>
> Hi Aric,
>
> I understand that "C" function transform dat3 in a variable for tcl,
> is it?

Thanks Aric,

It works perfectly, just i had to add to my "c" function:
Tcl_ObjSetVar2( interp, objv[3], NULL, tcl_dummy, TCL_LEAVE_ERR_MSG );

And calling the script with ;
set c [vecsub $a $b d]

it is giving me $c and $d with modified values.

0
2/7/2012 9:40:43 AM
On 7 feb, 09:49, Pablo <pablodecasti...@gmail.com> wrote:
> On 6 feb, 17:16, Aric Bills <aric.bi...@gmail.com> wrote:
>
>
>
>
>
>
>
>
>
> > On Feb 6, 2:16=A0am, Pablo <pablodecasti...@gmail.com> wrote:
>
> > > On 6 feb, 00:47, Alexandre Ferrieux <alexandre.ferri...@gmail.com>
> > > wrote:
>
> > > > On Feb 5, 9:42=A0pm, Pablo <pablodecasti...@gmail.com> wrote:
>
> > > > > Hello,
>
> > > > > To sum vectors i wrote a code like this; it is receiving 3 vector=
s
> > > > > data1, data2, data3. The diference between data1 and data2 is ret=
urned
> > > > > with Tcl_SetObjResult, but i would like modify data3, how can i m=
odify
> > > > > data3??
>
> > > > Let the script level do that; just return the value:
>
> > > > =A0 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 [upva=
r].
>
> > > > -Alex
>
> > > 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 $resul=
t
> > > (it is doing calling the procedure) and $dat3
>
> > > Thanks
>
> > 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:
>
> > =A0 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.
>
> Hi Aric,
>
> I understand that "C" function transform dat3 in a variable for tcl,
> is it?

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
0
2/7/2012 9:43:47 AM
On 7 feb, 06:43, Pablo <pablodecasti...@gmail.com> wrote:
> On 7 feb, 09:49, Pablo <pablodecasti...@gmail.com> wrote:
>
>
>
> > On 6 feb, 17:16, Aric Bills <aric.bi...@gmail.com> wrote:
>
> > > On Feb 6, 2:16=A0am, Pablo <pablodecasti...@gmail.com> wrote:
>
> > > > On 6 feb, 00:47, Alexandre Ferrieux <alexandre.ferri...@gmail.com>
> > > > wrote:
>
> > > > > On Feb 5, 9:42=A0pm, Pablo <pablodecasti...@gmail.com> wrote:
>
> > > > > > Hello,
>
> > > > > > To sum vectors i wrote a code like this; it is receiving 3 vect=
ors
> > > > > > data1, data2, data3. The diference between data1 and data2 is r=
eturned
> > > > > > with Tcl_SetObjResult, but i would like modify data3, how can i=
 modify
> > > > > > data3??
>
> > > > > Let the script level do that; just return the value:
>
> > > > > =A0 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 [up=
var].
>
> > > > > -Alex
>
> > > > Thanks Alex, but the idea is modify more than one var, the script i=
s
> > > > working like;
>
> > > > set result [vecsub $dat1 $dat2 $dat3], and i would like modify $res=
ult
> > > > (it is doing calling the procedure) and $dat3
>
> > > > Thanks
>
> > > 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:
>
> > > =A0 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.
>
> > Hi Aric,
>
> > I understand that "C" function transform dat3 in a variable for tcl,
> > is it?
>
> 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

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
0
2/7/2012 4:23:59 PM
On 7 feb, 17:23, Emiliano <emilianogavi...@gmail.com> wrote:
> On 7 feb, 06:43, Pablo <pablodecasti...@gmail.com> wrote:
>
>
>
>
>
>
>
>
>
> > On 7 feb, 09:49, Pablo <pablodecasti...@gmail.com> wrote:
>
> > > On 6 feb, 17:16, Aric Bills <aric.bi...@gmail.com> wrote:
>
> > > > On Feb 6, 2:16=A0am, Pablo <pablodecasti...@gmail.com> wrote:
>
> > > > > On 6 feb, 00:47, Alexandre Ferrieux <alexandre.ferri...@gmail.com=
>
> > > > > wrote:
>
> > > > > > On Feb 5, 9:42=A0pm, Pablo <pablodecasti...@gmail.com> wrote:
>
> > > > > > > Hello,
>
> > > > > > > To sum vectors i wrote a code like this; it is receiving 3 ve=
ctors
> > > > > > > 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:
>
> > > > > > =A0 set data3 [vecsub $data1 $data2]
>
> > > > > > Unless you have strong reasons (like modifying more than one va=
r),
> > > > > > there's no point in bringing to the C level the equivalent of [=
upvar].
>
> > > > > > -Alex
>
> > > > > 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 $r=
esult
> > > > > (it is doing calling the procedure) and $dat3
>
> > > > > Thanks
>
> > > > 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, yo=
u'd
> > > > call your command like this:
>
> > > > =A0 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.
>
> > > Hi Aric,
>
> > > I understand that "C" function transform dat3 in a variable for tcl,
> > > is it?
>
> > 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
>
> 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.
> 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
2/8/2012 4:43:31 PM
Reply: