Re: Best way to pass c++ pointer to tcl



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
.



Relevant Pages

  • [rfc] Replacing FNV and hash32 with Paul Hsiehs SuperFastHash
    ... I've recently noticed that hash table use in nullfs was inefficient, ... struct hpte *hpte; ... unsigned int hashed_key; ...
    (freebsd-hackers)
  • Re: [PATCH 2/2] Futex non-page-pinning fix
    ... Yes, it's effectively segmenting your hash table, which reduces the ... based on the "struct page *"). ... long do_futex(unsigned long uaddr, int op, int val, ... if (++ret <= nr_wake) { ...
    (Linux-Kernel)
  • Re: [PATCH] Split futex global spinlock futex_lock
    ... * Split the global futex_lock into every hash list lock. ... +struct futex_hash_bucket { ... static int futex_wake ... int ret; ...
    (Linux-Kernel)
  • Re: Best way to pass c++ pointer to tcl
    ... That's why I would like an "updated" piece of advice about my issue: ... Creating and Using Tcl Handles in C Extensions:http://wiki.tcl.tk/13881 ... So my Ext_Init allocates a struct like: ... The performance with this method is superior to a hash table, ...
    (comp.lang.tcl)
  • Re: [PATCH 2/2] Futex non-page-pinning fix
    ... D: clarify comment about hashing: we hash address of struct page, ... static inline struct list_head *hash_futex(struct page *page, int offset) ... ret = -EWOULDBLOCK; ...
    (Linux-Kernel)