• TCL "c" api question

    From aotto1968@aotto1968@t-online.de to comp.lang.tcl on Tue Apr 16 11:43:05 2024
    From Newsgroup: comp.lang.tcl

    Hi,

    → the tcl "C" structure "Tcl_Obj" is defined in "man Tcl_NewObj" like:

    THE TCL_OBJ STRUCTURE
    Each Tcl value is represented by a Tcl_Obj structure which is defined as follows.

    typedef struct Tcl_Obj {
    int refCount;
    char *bytes;
    int length;
    const Tcl_ObjType *typePtr;
    union {
    long longValue;
    double doubleValue;
    void *otherValuePtr;
    Tcl_WideInt wideValue;
    struct {
    void *ptr1;
    void *ptr2;
    } twoPtrValue;
    struct {
    void *ptr;
    unsigned long value;
    } ptrAndLongRep;
    } internalRep;
    } Tcl_Obj;

    My question is if I can use the "ptrAndLongRep" to store my data?

    My "Tcl_Obj" is a string representing of a *callback* and after the parsing of the string I create the
    "struct MkCallS*" data. The core problem is HOW to store this pointer in a "Tcl_Obj" as if the
    same "Tcl_Obj" is given as argument again the parsing have *not* be done again.

    usually a pointer can be addend to a PROC or an OO-OBJECT including
    a "destructor" to cleanup the data if the PROC or an OO-OBJECT is deleted.

    the "Tcl_Obj" has no official "interface" for adding a pointer etc.

    → I'm aware that the "ptrAndLongRep" solution has a memory-leak because if the "Tcl_Obj" disappears
    the "ptrAndLongRep" pointer is lost.

    → the "alternative" is that I always re-parse the "Tcl_Obj", even if the same "Tcl_Obj" is used ~1 Mio times
    in a loop


    mfg, ao
    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From Rich@rich@example.invalid to comp.lang.tcl on Tue Apr 16 14:17:28 2024
    From Newsgroup: comp.lang.tcl

    aotto1968 <aotto1968@t-online.de> wrote:
    → the tcl "C" structure "Tcl_Obj" is defined in "man Tcl_NewObj" like:
    ...
    struct {
    void *ptr;
    unsigned long value;
    } ptrAndLongRep;
    My question is if I can use the "ptrAndLongRep" to store my data?

    Reading into the man page you quote, this sentence occurs:

    Because of this representation invalidation and regeneration, it
    is dangerous for extension writers to access Tcl_Obj fields
    directly.

    Which implies a "no" answer to your question.

    My "Tcl_Obj" is a string representing of a callback and after the
    parsing of the string I create the "struct MkCallS*" data. The core
    problem is HOW to store this pointer in a "Tcl_Obj" as if the same
    "Tcl_Obj" is given as argument again the parsing have not be done
    again.

    Hmm? One idea that comes to mind is to store the pointer in an array
    in your extension, and store in the Tcl_Obj an integer that is the
    array index of the pointer in your array.

    That does add one level of indirection as to get to your pointer you effectively have to do:

    ptr = my_array[ getIntFromObj(Tcl_Obj) ];

    But it does mean you wouldn't have to 'reparse' a string back into the internal struct each time.

    Danger of course is any 'integer' would look like any other integer and
    so a 'random' integer obj that got used that happened to be within the
    range of allocted entries in your array would 'pick' that item, even if
    it was not the correct one to pick at that time.
    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From ted@loft.tnolan.com (Ted Nolan@tednolan to comp.lang.tcl on Tue Apr 16 14:49:21 2024
    From Newsgroup: comp.lang.tcl

    In article <uvm19o$100nc$1@dont-email.me>, Rich <rich@example.invalid> wrote: >aotto1968 <aotto1968@t-online.de> wrote:
    → the tcl "C" structure "Tcl_Obj" is defined in "man Tcl_NewObj" like:
    ...
    struct {
    void *ptr;
    unsigned long value;
    } ptrAndLongRep;
    My question is if I can use the "ptrAndLongRep" to store my data?

    Reading into the man page you quote, this sentence occurs:

    Because of this representation invalidation and regeneration, it
    is dangerous for extension writers to access Tcl_Obj fields
    directly.

    Which implies a "no" answer to your question.

    My "Tcl_Obj" is a string representing of a callback and after the
    parsing of the string I create the "struct MkCallS*" data. The core
    problem is HOW to store this pointer in a "Tcl_Obj" as if the same
    "Tcl_Obj" is given as argument again the parsing have not be done
    again.

    Hmm? One idea that comes to mind is to store the pointer in an array
    in your extension, and store in the Tcl_Obj an integer that is the
    array index of the pointer in your array.

    That does add one level of indirection as to get to your pointer you >effectively have to do:

    ptr = my_array[ getIntFromObj(Tcl_Obj) ];

    But it does mean you wouldn't have to 'reparse' a string back into the >internal struct each time.

    Danger of course is any 'integer' would look like any other integer and
    so a 'random' integer obj that got used that happened to be within the
    range of allocted entries in your array would 'pick' that item, even if
    it was not the correct one to pick at that time.

    In wrapping various libraries, I have often just returned pointer values
    to Tcl as integers. As long as the Tcl code treats it as opaque and
    just passes it back in when needed, it works fine. From time to time
    I have also passed structures in and out as base64 encoded text which
    also works fine as long as you are careful at the C level. Not the
    most efficient thing in the world, but not a problem for my cases.
    --
    columbiaclosings.com
    What's not in Columbia anymore..
    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From Ralf Fassel@ralfixx@gmx.de to comp.lang.tcl on Tue Apr 16 17:43:37 2024
    From Newsgroup: comp.lang.tcl

    * aotto1968 <aotto1968@t-online.de>
    | My "Tcl_Obj" is a string representing of a *callback* and after the parsing of the string I create the
    | "struct MkCallS*" data. The core problem is HOW to store this pointer in a "Tcl_Obj" as if the
    | same "Tcl_Obj" is given as argument again the parsing have *not* be done again.

    Can't you register a new obj type via

    https://www.tcl.tk/man/tcl8.5/TclLib/ObjectType.htm

    ? Seems like that would take care of the "not again" parsing if the Obj
    is already of the desired type... Haven't verified that, though...

    R'
    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From aotto1968@aotto1968@t-online.de to comp.lang.tcl on Tue Apr 16 19:34:17 2024
    From Newsgroup: comp.lang.tcl

    On 16.04.24 17:43, Ralf Fassel wrote:
    * aotto1968 <aotto1968@t-online.de>
    | My "Tcl_Obj" is a string representing of a *callback* and after the parsing of the string I create the
    | "struct MkCallS*" data. The core problem is HOW to store this pointer in a "Tcl_Obj" as if the
    | same "Tcl_Obj" is given as argument again the parsing have *not* be done again.

    Can't you register a new obj type via

    https://www.tcl.tk/man/tcl8.5/TclLib/ObjectType.htm

    ? Seems like that would take care of the "not again" parsing if the Obj
    is already of the desired type... Haven't verified that, though...

    R'

    I know that a new object type could do the job but I thing this is "over-engineering" just to store an
    pointer in a "Tcl_Obj"

    The "integer" idea is not working because the INPUT "Tcl_Obj" is *shared* with the calling *level*

    mfg
    --- Synchronet 3.20a-Linux NewsLink 1.114