Re: Best way to pass c++ pointer to tcl
- From: GPS <georgeps@xxxxxxxxxxxx>
- Date: Sun, 16 Nov 2008 15:45:05 -0700
thibault.daoulas wrote:
Hi everybody,
I have read several topics around this, but quite old and different.
That's why I would like an "updated" piece of advice about my issue :
I have in my c++ code a pointer to u_char's (u_char *), and I want
this to be reachable from my Tcl/Tk code. Everything is pretty
straightforward with simple types like int, long, etc., but I do not
see clearly how this can be efficiently done for u_char *, or whatever
c++ pointer.
I was thinking about creating a new tcl command, like "$d getdata"
which would return the u_char* corresponding to my variable $d, via a
tcl.result()-like method in my c++ class, but it does not seem to be
as easy as I thought.
Do you have a clue about this?
Cheers,
Thibault.
Creating and Using Tcl Handles in C Extensions:
http://wiki.tcl.tk/13881
Be aware of the problems at the end of the page with the code.
I originally used that type of code, but I've found better performance by
using integers that refer to offsets in a structure.
So my Ext_Init allocates a struct like:
struct ext {
void **structures;
int allocated;
int used;
};
I also allocate a few ext->structures to start with in Ext_Init.
Then I clean that up with Tcl_CallWhenDeleted() when the interp gets
destroyed.
The Tcl_Obj command Ext_Create is passed the struct ext * via its client
data.
The bulk of the code might look something like this:
int i;
ext->used++;
if(ext->used >= ext->allocated) {
size_t newsize = ext->allocated * 2;
ext->structures = (void *)Tcl_Realloc((void *)ext->structures,
sizeof(*(ext->structures)) * newsize);
/* Initialize the new pointers to NULL. */
for(i = ext->allocated; i < newsize; ++i) {
ext->structures[i] = NULL;
}
ext->allocated = newsize;
}
/* Now find the first free slot.
* This could be a bit smarter if the table just grew.
*/
for(i = 0; i < ext->allocated; ++i) {
if(NULL == ext->structures[i]) {
ext->structures[i] = ext_alloc_something();
Tcl_SetObjResult(interp, Tcl_NewIntObj(i));
return TCL_OK;
}
}
Tcl_Panic("invalid accounting for ext data structure");
return TCL_ERROR;
Then in void *Ext_GetSomePointer(interp, struct ext *ext, int i); that takes
an integer and returns NULL or a valid pointer, you do something like this:
void *ptr;
/*Validate the offset.*/
if(i >= 0 && i < ext->allocated && ext->structures[i]) {
ptr = ext->structures[i];
return ptr;
}
Tcl_SetObjResult(interp, Tcl_ObjPrintf("invalid handle: %d", i));
return NULL;
The performance with this method is superior to a hash table, and there are
never any hash collisions to worry about, or hash attacks you might be
vulnerable to. It's also more efficient in terms of memory usage in
comparison to a Tcl hash table too. When I've explained this before, it's
fallen on deaf ears. I hope this makes more sense today to the rest of the
Tcl community.
You can also have the pretty "file#%d" type of descriptors quite easily with
a bit of string manipulation, while retaining the O(1) behavior.
-George
.
- Follow-Ups:
- Re: Best way to pass c++ pointer to tcl
- From: thibault.daoulas
- Re: Best way to pass c++ pointer to tcl
- References:
- Best way to pass c++ pointer to tcl
- From: thibault.daoulas
- Best way to pass c++ pointer to tcl
- Prev by Date: Re: Best way to pass c++ pointer to tcl
- Next by Date: Re: expect has versions of tcl functions..
- Previous by thread: Re: Best way to pass c++ pointer to tcl
- Next by thread: Re: Best way to pass c++ pointer to tcl
- Index(es):
Relevant Pages
|