From: haferbox on
All,

Let me start by saying I am trying to use the TCL C Procedures for the
very first time. I’m comfortable with C and very familiar with Tcl.


History ( you probably don’t care but…):
I recently decided to “extend a Tcl application” with new commands.
The commands allow me to interact with a .dll that was written for my
company many years ago and cannot be modified. However the dll has a
nice interface and I have the h files so I have been able to create my
own loadable dll.

My new dll is able to load the older dll and even map my c functions
into the dlls functions. The first couple of functions I tried were
very simple and the older dll returned nothing more than a pointer. I
thought I was on my way..

I’m now working on a command that takes 4 lists of doubles from the
command line, parses the lists into a large C struct and then passes a
pointer to the struct to the older dll. This is where I started having
issues. Im not yet worried about the call to the older dll because the
parsing does not work and this is what Im asking for help on.

Issue:
Here are two functions that attempt to parse the 4 input lists of the
command and then store the data into structures. The parsing works on
the first two lists and then crashes the app on the third list. The
code that parses the lists is literally the same function so Im not
sure what the issue is.

I suspect it is my use of Tcl_Obj * but as I said before this is new
to me so Im not sure.

Code:

#define CORE_NUM_FREQ_POINTS 4

typedef struct {
double mag;
double phase;
} CoreMagPhasePoint;

int
GetGParamData(
Tcl_Interp *interp,
const char *description,
CoreMagPhasePoint *pMagPhasePoint[],
Tcl_Obj *const objv)
{
int i = 0;
int cnt = 0;
Tcl_Obj **lstPtr = NULL;

if( Tcl_ListObjGetElements( interp, objv, &cnt, &lstPtr) !=
TCL_OK ) {
return TCL_ERROR;
}

if (cnt != (CORE_NUM_FREQ_POINTS * 2)) {
char buf[256];
sprintf(buf, "incomplete %s must be: %i pairs of mag phase",
description, CORE_NUM_FREQ_POINTS);
Tcl_SetResult(interp, buf, TCL_STATIC);
return TCL_ERROR;
}

for (i = 0; i < (CORE_NUM_FREQ_POINTS*2); i+=2) {
double dbl;

if (Tcl_GetDoubleFromObj(interp, lstPtr[i], &dbl) != TCL_OK) {
return TCL_ERROR;
}

(*pMagPhasePoint)[i].mag = dbl;

if (Tcl_GetDoubleFromObj(interp, lstPtr[i+1], &dbl) != TCL_OK)
{
return TCL_ERROR;
}
(*pMagPhasePoint)[i+1].phase = dbl;
}

return TCL_OK;
}

int
GParamSet (
Tcl_Interp *interp,
const char *description,
CoreMagPhasePoint *pMagPhasePoint[],
Tcl_Obj *const objv)
{
CoreMagPhasePoint g24[CORE_NUM_FREQ_POINTS];
CoreMagPhasePoint g42[CORE_NUM_FREQ_POINTS];
CoreMagPhasePoint g44[CORE_NUM_FREQ_POINTS];
CoreMagPhasePoint zsl[CORE_NUM_FREQ_POINTS];
CoreMagPhasePoint *pMagPhase;

if (objc != 7) {
Tcl_WrongNumArgs(interp, 3, objv, "g24MagPhsLst g42MagPhsLst
g44MagPhsLst zslMagPhsLst");
return TCL_ERROR;
}

/* get the 2 to 4 gparams */
pMagPhase = g24;
if ( GetGParamData(interp, "g24MagPhsLst", &pMagPhase, objv[3]) !=
TCL_OK ) {
return TCL_ERROR;
}

/* get the 4 to 2 gparams */
pMagPhase = g42;
if ( GetGParamData(interp, "g42MagPhsLst", &pMagPhase, objv[4]) !=
TCL_OK ) {
return TCL_ERROR;
}

/* get the 4 to 4 gparams */
pMagPhase = g44;
if ( GetGParamData(interp, "g44MagPhsLst", &pMagPhase, objv[5]) !=
TCL_OK ) {
return TCL_ERROR;
}

/* get the zsl gparams */
pMagPhase = zsl;
if ( GetGParamData(interp, "zslMagPhsLst", &pMagPhase, objv[6]) !=
TCL_OK ) {
return TCL_ERROR;
}

.
.
.
return TCL_OK;
}


Here is the Tcl call that eventually runs this code:

tclslac gparam set {0 1 2 3 4 5 6 7 8} {0 1 2 3 4 5 6 7 8} {0 1 2 3 4
5 6 7 8} {0 1 2 3 4 5 6 7 8}

I have done quite a bit of debugging and have narrowed down the issue
(on a windows xp PC) to the third call to the GetGParamsData function.
The line "(*pMagPhasePoint)[i].mag = dbl;" appears to crash the code
and I’m not sure why. Again II suspect that I am somehow not using the
Tcl_Obj values correctly but Im so new to this I cant determine how/
why.

Thanks for any help you can provide
-s

Also, there is a little documentation about the Tcl C functions in the
Practical Programming In Tcl and Tk book but its brief. Can anyone
point me to a document or book that covers the C interface in detail?
From: Georgios Petasis on
Do you know that there exists a free app named swig (www.swig.org) that
can take your .h file and produce all the C code required to call it
from Tcl (and many other languages)?

I use it all the time :-)

With a little extra (SWIG specific code in the .h file) you can even
expose STL objects!

George

στις 1/7/2010 20:58, O/H haferbox έγραψε:
> All,
>
> Let me start by saying I am trying to use the TCL C Procedures for the
> very first time. I'm comfortable with C and very familiar with Tcl.
>
>
> History ( you probably don't care but…):
> I recently decided to “extend a Tcl application” with new commands.
> The commands allow me to interact with a .dll that was written for my
> company many years ago and cannot be modified. However the dll has a
> nice interface and I have the h files so I have been able to create my
> own loadable dll.
>
> My new dll is able to load the older dll and even map my c functions
> into the dlls functions. The first couple of functions I tried were
> very simple and the older dll returned nothing more than a pointer. I
> thought I was on my way..
>
> I'm now working on a command that takes 4 lists of doubles from the
> command line, parses the lists into a large C struct and then passes a
> pointer to the struct to the older dll. This is where I started having
> issues. Im not yet worried about the call to the older dll because the
> parsing does not work and this is what Im asking for help on.
>
> Issue:
> Here are two functions that attempt to parse the 4 input lists of the
> command and then store the data into structures. The parsing works on
> the first two lists and then crashes the app on the third list. The
> code that parses the lists is literally the same function so Im not
> sure what the issue is.
>
> I suspect it is my use of Tcl_Obj * but as I said before this is new
> to me so Im not sure.
>
> Code:
>
> #define CORE_NUM_FREQ_POINTS 4
>
> typedef struct {
> double mag;
> double phase;
> } CoreMagPhasePoint;
>
> int
> GetGParamData(
> Tcl_Interp *interp,
> const char *description,
> CoreMagPhasePoint *pMagPhasePoint[],
> Tcl_Obj *const objv)
> {
> int i = 0;
> int cnt = 0;
> Tcl_Obj **lstPtr = NULL;
>
> if( Tcl_ListObjGetElements( interp, objv,&cnt,&lstPtr) !=
> TCL_OK ) {
> return TCL_ERROR;
> }
>
> if (cnt != (CORE_NUM_FREQ_POINTS * 2)) {
> char buf[256];
> sprintf(buf, "incomplete %s must be: %i pairs of mag phase",
> description, CORE_NUM_FREQ_POINTS);
> Tcl_SetResult(interp, buf, TCL_STATIC);
> return TCL_ERROR;
> }
>
> for (i = 0; i< (CORE_NUM_FREQ_POINTS*2); i+=2) {
> double dbl;
>
> if (Tcl_GetDoubleFromObj(interp, lstPtr[i],&dbl) != TCL_OK) {
> return TCL_ERROR;
> }
>
> (*pMagPhasePoint)[i].mag = dbl;
>
> if (Tcl_GetDoubleFromObj(interp, lstPtr[i+1],&dbl) != TCL_OK)
> {
> return TCL_ERROR;
> }
> (*pMagPhasePoint)[i+1].phase = dbl;
> }
>
> return TCL_OK;
> }
>
> int
> GParamSet (
> Tcl_Interp *interp,
> const char *description,
> CoreMagPhasePoint *pMagPhasePoint[],
> Tcl_Obj *const objv)
> {
> CoreMagPhasePoint g24[CORE_NUM_FREQ_POINTS];
> CoreMagPhasePoint g42[CORE_NUM_FREQ_POINTS];
> CoreMagPhasePoint g44[CORE_NUM_FREQ_POINTS];
> CoreMagPhasePoint zsl[CORE_NUM_FREQ_POINTS];
> CoreMagPhasePoint *pMagPhase;
>
> if (objc != 7) {
> Tcl_WrongNumArgs(interp, 3, objv, "g24MagPhsLst g42MagPhsLst
> g44MagPhsLst zslMagPhsLst");
> return TCL_ERROR;
> }
>
> /* get the 2 to 4 gparams */
> pMagPhase = g24;
> if ( GetGParamData(interp, "g24MagPhsLst",&pMagPhase, objv[3]) !=
> TCL_OK ) {
> return TCL_ERROR;
> }
>
> /* get the 4 to 2 gparams */
> pMagPhase = g42;
> if ( GetGParamData(interp, "g42MagPhsLst",&pMagPhase, objv[4]) !=
> TCL_OK ) {
> return TCL_ERROR;
> }
>
> /* get the 4 to 4 gparams */
> pMagPhase = g44;
> if ( GetGParamData(interp, "g44MagPhsLst",&pMagPhase, objv[5]) !=
> TCL_OK ) {
> return TCL_ERROR;
> }
>
> /* get the zsl gparams */
> pMagPhase = zsl;
> if ( GetGParamData(interp, "zslMagPhsLst",&pMagPhase, objv[6]) !=
> TCL_OK ) {
> return TCL_ERROR;
> }
>
> .
> .
> .
> return TCL_OK;
> }
>
>
> Here is the Tcl call that eventually runs this code:
>
> tclslac gparam set {0 1 2 3 4 5 6 7 8} {0 1 2 3 4 5 6 7 8} {0 1 2 3 4
> 5 6 7 8} {0 1 2 3 4 5 6 7 8}
>
> I have done quite a bit of debugging and have narrowed down the issue
> (on a windows xp PC) to the third call to the GetGParamsData function.
> The line "(*pMagPhasePoint)[i].mag = dbl;" appears to crash the code
> and I'm not sure why. Again II suspect that I am somehow not using the
> Tcl_Obj values correctly but Im so new to this I cant determine how/
> why.
>
> Thanks for any help you can provide
> -s
>
> Also, there is a little documentation about the Tcl C functions in the
> Practical Programming In Tcl and Tk book but its brief. Can anyone
> point me to a document or book that covers the C interface in detail?

From: haferbox on
This looks promising... however, I have only briefly scanned the doc
and I only seen examples where the c code is available. Can you point
me to a location or example in the doc that uses only .h files I'm in
a bit of a hurry and a 700 page document is daunting.

Thanks for the feedback.
-s

I would still like to understand what Im doing wrong in my example
code if anyone has input.
From: Georgios Petasis on
στις 1/7/2010 22:11, O/H haferbox έγραψε:
> This looks promising... however, I have only briefly scanned the doc
> and I only seen examples where the c code is available. Can you point
> me to a location or example in the doc that uses only .h files I'm in
> a bit of a hurry and a 700 page document is daunting.
>
> Thanks for the feedback.
> -s
>
> I would still like to understand what Im doing wrong in my example
> code if anyone has input.

Perhaps:


swig -Wall -c++ -tcl -module PackageName -namespace -pkgversion 1.0
your_file.h

is a good start?

George
From: Georgios Petasis on
στις 1/7/2010 22:11, O/H haferbox έγραψε:
> I would still like to understand what Im doing wrong in my example
> code if anyone has input.


pMagPhase = g24;
CoreMagPhasePoint g24[CORE_NUM_FREQ_POINTS];

inside GetGParamData:
for (i = 0; i < (CORE_NUM_FREQ_POINTS*2); i+=2)
...
(*pMagPhasePoint)[i].mag = dbl;
(*pMagPhasePoint)[i+1].phase = dbl;

Isn't the code expected to crash when you allocate an array of
size CORE_NUM_FREQ_POINTS and you set values at indexes greater than the
size of the array?

George