Hi,
I'm cracking on with my first Tcl extension. It wraps a set of C++ code
with a function that returns a vector of strings. I want to expose that
to the Tcl user, so I have something like
int myExtension_nameCmd (ClientData clientData, TclInterp *interp,
int objc, Tcl_Obj *const objv[])
{
if (objc != 2) {
Tcl_WrongNumArgs (interp, 2, objv, nullptr);
return TCL_ERROR;
}
Tcl_Obj *rslt (Tcl_NewListObj (0, nullptr));
for (auto name : names ()) {
if (Tcl_ListObjAppendElement (interp, rslt,
Tcl_NewStringObj (name.c_str (),
-1))
!= TCL_OK) {
return TCL_ERROR;
}
}
Tcl_SetObjResult (interp, rslt);
return TCL_OK;
}
This works Just Fine (tm) normally - in the sense that the Tcl user gets
the list that he should do, but is it "correct" in the way it handles reference counting?
I imagine that if all is well, then the result list and all the objects
it contains get handed over to a Tcl interpreter when I call Tcl_SetObjResult and that interpreter looks after freeing up the
objects' memory at the appropriate moment.
I'm worried what happens if there's an error constructing, say the third object to add to the list. Do I need to free the memory used by the list
and the first two objects and if so how?
I've tried reading the documentation in various directions (including
from beginning to end, in that order) and I'm not really any the wiser.
Does it answer my question, and if so where?
Many thanks.
Alan
if (Tcl_ListObjAppendElement (interp, rslt,--- Synchronet 3.22a-Linux NewsLink 1.2
Tcl_NewStringObj (name.c_str (),
-1))
!= TCL_OK) {
return TCL_ERROR;
}
}
Tcl_SetObjResult (interp, rslt);
return TCL_OK;
Keep asking, it is complex !
Bonjour,
Since you propose it ... Since memory management is complex, have you an an idea why
the Tcl command "memory" is not systematically available ? Can it be a security
problem ? More surprising, it is probably the only Tcl command which is not described in Ashok's books !
Olivier <[email protected]d> posted:
Bonjour,
Since you propose it ... Since memory management is complex, have you an an idea why
the Tcl command "memory" is not systematically available ? Can it be a security
problem ? More surprising, it is probably the only Tcl command which is not described in Ashok's books !
The extra checks that `memory` does have a high runtime cost in processing time and extra memory allocation for guard areas. So it's only enabled in special debug builds.
Simply addAbu, this is a correct proposal, no criticism here.
Tcl_DecrRefCount(rslt) before returning TCL_ERROR;
OR: If you move theSuper-smart proposal, Ralph !
Tcl_SetObjResult (interp, rslt);
*before* the loop:
Tcl_Obj *rslt (Tcl_NewListObj (0, nullptr));
!! Tcl_SetObjResult (interp, rslt);
for (auto name : names ()) {
if (Tcl_ListObjAppendElement (interp, rslt,
Tcl_NewStringObj (name.c_str (),
-1))
!= TCL_OK) {
return TCL_ERROR;
}
}
then the rslt object is handled by TCL:
- Tcl_SetObjResult() will incr the refcount of rslt
- any error in Tcl_ListObjAppendElement() will set a new result in the
interp, which does a decr in the current result first, which deletes
rslt and all its Elements.
* Harald Oehlmann <[email protected]>Thanks, and sorry for the spelling of your name,
| But is the error case of Tcl_ListObjAppendElement a realistic case?
| To my knowledge, it may only error out, if the first argument may not
| be converted to a list and this may not happen here...
This is probably true for this particular case - here omitting the error check does not hurt.
My suggestion was meant to show other possibilities to avoid adding
incr/decr all over the place (and missing some in later changes of the
code if the function is larger than a 10-liner).
* Alan Grunwald <[email protected]>I can second that - once you get the wrapper correct, you'll never have
| I'm cracking on with my first Tcl extension. It wraps a set of C++
| code with a function that returns a vector of strings.
If you're using c++ anyway, why not wrap the TCL Objs in a class which
does the refcounting for you:
class managed_objptr {
Hi,
I'm cracking on with my first Tcl extension. It wraps a set of C++ code
with a function that returns a vector of strings. I want to expose that
to the Tcl user, so I have something like
int myExtension_nameCmd (ClientData clientData, TclInterp *interp,
int objc, Tcl_Obj *const objv[])
{
if (objc != 2) {
Tcl_WrongNumArgs (interp, 2, objv, nullptr);
return TCL_ERROR;
}
Tcl_Obj *rslt (Tcl_NewListObj (0, nullptr));
for (auto name : names ()) {
if (Tcl_ListObjAppendElement (interp, rslt,
Tcl_NewStringObj (name.c_str (),
-1))
!= TCL_OK) {
return TCL_ERROR;
}
}
Tcl_SetObjResult (interp, rslt);
return TCL_OK;
}
This works Just Fine (tm) normally - in the sense that the Tcl user gets
the list that he should do, but is it "correct" in the way it handles reference counting?
I imagine that if all is well, then the result list and all the objects
it contains get handed over to a Tcl interpreter when I call Tcl_SetObjResult and that interpreter looks after freeing up the
objects' memory at the appropriate moment.
I'm worried what happens if there's an error constructing, say the third object to add to the list. Do I need to free the memory used by the list
and the first two objects and if so how?
I've tried reading the documentation in various directions (including
from beginning to end, in that order) and I'm not really any the wiser.
Does it answer my question, and if so where?
| Sysop: | DaiTengu |
|---|---|
| Location: | Appleton, WI |
| Users: | 1,142 |
| Nodes: | 10 (0 / 10) |
| Uptime: | 93:08:05 |
| Calls: | 14,704 |
| Calls today: | 2 |
| Files: | 186,497 |
| D/L today: |
2,351 files (779M bytes) |
| Messages: | 2,551,657 |