Re: need a tiny help with my SWIG'd program
- From: Robert Heller <heller@xxxxxxxxxxxx>
- Date: Thu, 28 Feb 2008 20:43:38 +0100
At Thu, 28 Feb 2008 18:55:10 +0200 Georgios Petasis <petasis@xxxxxxxxxxxxxxxxx> wrote:
O/H Georgios Petasis ÎγÏ?αÏ?ε:
O/H Mel ÎγÏ?αÏ?ε:
the C function i am calling requires a:
'char ** myvar"
what would I be passing as TCL var to this function ?
void junk(char **' myvar)
in tcl I would call something like:
junk <what should I put here>
many thanks for your help
It is not so easy :-)
char ** means an array of null terminated strings. There in nothing in
tcl that can be converted to this type. So, you have to add to your
header file some C code to generate such structures.
For example, in a similar situation I have added the following helper code:
#ifdef SWIG
%rename(String) array_string;
#endif
#if defined(ARRAY_STRING_CLASS)
class array_string {
char **array;
int _size;
public:
array_string(int size) {
_size=size;
array = (char **) Tcl_Alloc(sizeof(char*)*_size);
if (array) for(int i=0; i<_size;++i) array[i]=NULL;
}
void setitem(int i, char* value) {
if (!array || i < 0 || i >= _size) return;
if(array[i]) Tcl_Free(array[i]);
array[i]=Tcl_Alloc(sizeof(char)*(strlen(value)+2));
strcpy(array[i], value);
}
char *getitem(int i) {
if (!array || i<0 || i>=_size) return NULL;return array[i];
}
char** cast(void) {return array;}
~array_string() {
if (array) {
for(int i=0; i<_size; ++i) {
if (array[i]) Tcl_Free(array[i]);
}
Tcl_Free((char *)array);
}
}
};
#endif /* ARRAY_STRING_CLASS */
Them, from tcl you can do (assuming that you have enabled shadow classes):
String x 5
x setitem 0 "string 1"
x setitem 1 "string 2"
...
junk [x cast]
## delete x...
delete_String x
George
Of course, you could also try to convert a tcl list into this, but its
easier to do this from the tcl level than at the C level :-)
The ultimate solution will be to do tcl list -> char ** conversion as an
argument template, and just call your function with a tcl list as a
parameter. Perhaps there is some ready code if you search at google.
From my Model Railroad System (cmri.h):
#ifdef SWIG
/*
* Typemaps for handling the List class. This maps a Tcl list of
integers to
* a List class instance.
*/
%typedef List *ListP; // Help SWIG's pattern matching
/*
* Input method: convert a Tcl list (of integers) to a freshly allocated
List
* object.
*/
%typemap(tcl8,in) const List * {
Tcl_Obj **objvPtr;
int objcPtr,i;
if (Tcl_ListObjGetElements(interp,$input,&objcPtr,&objvPtr) !=
TCL_OK)
return(TCL_ERROR);
$1 = new List(objcPtr);
for (i = 0; i < objcPtr; i++) {
if (Tcl_GetIntFromObj(interp,objvPtr[i],&((*$1)[i])) !=
TCL_OK)
return(TCL_ERROR);
}
}
%typemap(tcl8,freearg) const List * {
delete $1;
}
/*
* Output (function result) method: convert the List object pointer to a
Tcl
* list. Free up the List object pointer. If the result was a NULL,
return
* an empty Tcl list.
*/
%typemap(tcl8,out) ListP {
int i, length;
if ($1 == NULL) length = 0;
else length = $1->Length();
Tcl_Obj * tcl_result = $result;
Tcl_SetListObj(tcl_result,0,NULL);
for (i = 0; i < length; i++) {
if
(Tcl_ListObjAppendElement(interp,tcl_result,Tcl_NewIntObj((*$1)[i])) !=
TCL_OK)
return TCL_ERROR;
}
if ($1 != NULL) delete $1;
}
#endif
#ifndef SWIG
/** @memo A C++ mapping for a Tcl list.
* @doc Re-sizable (manually only). Used to pass lists of integers
(such as
* port values) to and from the low-level code, where these values are
* encoded and decoded to/from the serial interface
* cards.
*/
class List {
public:
/** @memo Constructor.
* @doc Construct a vector of a specific number of elements.
* @param l The number of elements to allocate.
*/
List(int l=0);
/** @memo Destructor.
* @doc Free up memory.
*/
~List();
/** The Length() member function returns the length of the
vector.
*/
int Length() const {return length;}
/** Read/write indexing accessor. Returns a reference to the
* $i^{th}$ element.
* @param i The index to access.
*/
int & operator [](int i);
/** @memo Read only indexing accessor.
* @doc Returns the value of the $i^{th}$ element.
* @param i The index to access.
*/
int operator [](int i) const;
/** The Resize() member function re-sizes the vector. If the
vector
* is shortened, elements off the end are discarded.
* @param l The number of elements to allocate.
*/
void Resize(int l);
private:
/** Length of the allocated vector.
*/
int length;
/** Vector of elements.
*/
int *elements;
};
/** Pointer typedef.
*/
typedef List *ListP;
#endif
Note: this is for a list of integers, but the principle is the same. I
also have code doing something similar with C++ (STL) string vectors:
#include <string>
#include <vector>
typedef vector<string> stringVector;
/*
* Type map for stringVector: convert from a Tcl list on input.
*/
/*
* On input: allocate a stringVector and fill it from the input list argument.
*/
%typemap(tcl8,in) const stringVector * {
Tcl_Obj **objvPtr;
int objcPtr,i;
if (Tcl_ListObjGetElements(interp,$input,&objcPtr,&objvPtr) != TCL_OK)
return(TCL_ERROR);
$1 = new stringVector;
#ifdef DEBUG
cerr << "*** Passing list of " << objcPtr << " strings as a stringVector" << endl;
#endif
for (i = 0; i < objcPtr; i++) {
$1->push_back(string(Tcl_GetString(objvPtr[i])));
}
}
/*
* Free allocated space.
*/
%typemap(tcl8,freearg) const stringVector * {
delete $1;
}
%typemap(tcl8,in) const stringVector {
Tcl_Obj **objvPtr;
int objcPtr,i;
if (Tcl_ListObjGetElements(interp,$input,&objcPtr,&objvPtr) != TCL_OK)
return(TCL_ERROR);
#ifdef DEBUG
cerr << "*** Passing list of " << objcPtr << " strings as a doubleVector" << endl;
#endif
for (i = 0; i < objcPtr; i++) {
$1.push_back(string(Tcl_GetString(objvPtr[i])));
}
}
Again, the concept is straight forward and it should be easy to adapt to
a 'char **'.
George
--
Robert Heller -- Get the Deepwoods Software FireFox Toolbar!
Deepwoods Software -- Linux Installation and Administration
http://www.deepsoft.com/ -- Web Hosting, with CGI and Database
heller@xxxxxxxxxxxx -- Contract Programming: C/C++, Tcl/Tk
.
- References:
- Re: need a tiny help with my SWIG'd program
- From: Georgios Petasis
- Re: need a tiny help with my SWIG'd program
- Prev by Date: Re: need a tiny help with my SWIG'd program
- Next by Date: Re: need a tiny help with my SWIG'd program
- Previous by thread: Re: need a tiny help with my SWIG'd program
- Next by thread: Re: need a tiny help with my SWIG'd program
- Index(es):
Relevant Pages
|