|
|
 |
 |
 |
 |
TCL(Tool Command Language) Scripting
|
 |
 |
 |
 |
 |
 |
 |
 |
Adding a function's argument while preserving the API compatibility?
Hello! The Tcl's Tcl_SetFromAnyProc type is defined (in tcl.h) as: typedef int (Tcl_SetFromAnyProc) _ANSI_ARGS_((Tcl_Interp *interp, struct Tcl_Obj *objPtr)); The function's purpose is: /* Called to convert the object's internal * rep to this type. Frees the internal rep * of the old type. Returns TCL_ERROR on * failure. */ An actual implementation of the function is presumed to know, what the type is. However, in certain cases it may desirable to share the same function between different types. For that the function needs the third parameter: "const struct Tcl_ObjType *" and my question is: what's the best way to add it? Obviously, I'm trying to minimize/eliminate the need to modify the existing body of extensions (some of them no longer maintained), that create custom Tcl-types. There is, probably, no need to worry about the ABI compatibility -- on most platforms anyway. But the API? A compiler warning would be acceptable, but an error is a problem... Should the Tcl_SetFromAnyProc become a union of the old and the new function types? Any other ideas? Thanks! -mi
On May 9, 7:48 pm, "Mikhail T." <mi+use@aldan.algebra.com> wrote: > Hello! > The Tcl's Tcl_SetFromAnyProc type is defined (in tcl.h) as: > .... > An actual implementation of the function is presumed to know, what the > type is. However, in certain cases it may desirable to share the same > function between different types. > For that the function needs the third parameter: "const struct > Tcl_ObjType *" and my question is: what's the best way to add it? > ... > Should the Tcl_SetFromAnyProc become a union of the old and the new > function types? Any other ideas?
Why not leaving the API as is, and simply do something like int SetFooFromAnyProc (Tcl_Interp *interp, Tcl_Obj *objPtr) { Tcl_ObjType *fooPtr = &fooType; return GenericSetFromAnyProc(interp, objPtr, fooPtr);
}
Mikhail T. wrote: > Hello! > The Tcl's Tcl_SetFromAnyProc type is defined (in tcl.h) as: > typedef int (Tcl_SetFromAnyProc) _ANSI_ARGS_((Tcl_Interp *interp, > struct Tcl_Obj *objPtr)); > The function's purpose is: > /* Called to convert the object's internal > * rep to this type. Frees the internal rep > * of the old type. Returns TCL_ERROR on > * failure. */ > An actual implementation of the function is presumed to know, what the > type is. However, in certain cases it may desirable to share the same > function between different types.
why? > For that the function needs the third parameter: "const struct > Tcl_ObjType *" and my question is: what's the best way to add it? > Obviously, I'm trying to minimize/eliminate the need to modify the > existing body of extensions (some of them no longer maintained), that > create custom Tcl-types.
can't be done. > There is, probably, no need to worry about the ABI compatibility -- on > most platforms anyway. But the API? A compiler warning would be > acceptable, but an error is a problem... > Should the Tcl_SetFromAnyProc become a union of the old and the new > function types? Any other ideas?
what would this buy you? the SetFromAny proc is called when needed, how would it know which flavor to call if the pointer could be to 2 different functions? you would have to change all the core code as well as any extensions and again I ask why? if you have type A and type B what possible benefit could a single function give you? current way (imho good) makeItA(...) { do stuff to create an A internal rep }
makeItB(...) { do stuff to create a B internal rep }
proposed way makeItSomething(..., TYPE) { if (TYPE == A) { do stuff to create an A internal rep } elseif (TYPE == B) { do stuff to create a B internal rep } else { uh oh } }
how does that help in any way to justify changing the framework of TclObjs? Bruce
Mikhail T. wrote, On 09/05/07 23:48: > Hello! > The Tcl's Tcl_SetFromAnyProc type is defined (in tcl.h) as: > typedef int (Tcl_SetFromAnyProc) _ANSI_ARGS_((Tcl_Interp *interp, > struct Tcl_Obj *objPtr));
<snip> > For that the function needs the third parameter: "const struct > Tcl_ObjType *" and my question is: what's the best way to add it? > Obviously, I'm trying to minimize/eliminate the need to modify the > existing body of extensions (some of them no longer maintained), that > create custom Tcl-types. > There is, probably, no need to worry about the ABI compatibility -- on > most platforms anyway. But the API? A compiler warning would be > acceptable, but an error is a problem... > Should the Tcl_SetFromAnyProc become a union of the old and the new > function types? Any other ideas?
I'm posting from comp.lang.c, we do not deal with Tcl here, so would people please restrict follow-ups where appropriate. I am going to assume that each of these extensions are registered in some manner. Given that, any extension that uses your new signature for this function can tell the rest of Tcl that this is what it is doing. Based on this, the rest of the Tcl code will be able to call the function using the appropriate signature. One thing the C standard guarantees that may (depending on how things are coded) help is that you are explicitly allowed to cast pointers to functions to function types with different signatures, the only restriction is that you *must* cast it back to the correct type before calling it. I am setting followups on this post to just comp.lang.tcl because I expect this to rapidly wander in to Tcl rather than C issues, but please feel free to override the followups if you want clarification on the C issues. Would others please also consider carefully whether their replies in other parts of the thread are topical in comp.lang.c where only C is topical. -- Flash Gordon
Mikhail T. schreef:
> Hello! > The Tcl's Tcl_SetFromAnyProc type is defined (in tcl.h) as: > typedef int (Tcl_SetFromAnyProc) _ANSI_ARGS_((Tcl_Interp *interp, > struct Tcl_Obj *objPtr)); > The function's purpose is: > /* Called to convert the object's internal > * rep to this type. Frees the internal rep > * of the old type. Returns TCL_ERROR on > * failure. */ > An actual implementation of the function is presumed to know, what the > type is. However, in certain cases it may desirable to share the same > function between different types. > For that the function needs the third parameter: "const struct > Tcl_ObjType *" and my question is: what's the best way to add it? > Obviously, I'm trying to minimize/eliminate the need to modify the > existing body of extensions (some of them no longer maintained), that > create custom Tcl-types. > There is, probably, no need to worry about the ABI compatibility -- on > most platforms anyway. But the API? A compiler warning would be > acceptable, but an error is a problem... > Should the Tcl_SetFromAnyProc become a union of the old and the new > function types? Any other ideas? > Thanks! > -mi
Am I understanding correctly that breaking ABI compatibility means I would have to recompile all my extensions? In that case, this would be a big showstopper. Mark
Mikhail T. wrote: >The Tcl's Tcl_SetFromAnyProc type is defined (in tcl.h) as: >typedef int (Tcl_SetFromAnyProc) _ANSI_ARGS_((Tcl_Interp *interp, > struct Tcl_Obj *objPtr)); >The function's purpose is: > /* Called to convert the object's internal > * rep to this type. Frees the internal rep > * of the old type. Returns TCL_ERROR on > * failure. */ >An actual implementation of the function is presumed to know, what the >type is. However, in certain cases it may desirable to share the same >function between different types. >For that the function needs the third parameter: "const struct >Tcl_ObjType *" and my question is: what's the best way to add it?
Don't. The SetFromAny() hook should be considered deprecated, along with Tcl_RegisterObjType() and Tcl_ConvertToType(). Tcl_ObjType's don't need to provide a SetFromAny() hook at all; I for one strongly recommend that they do not. --Joe English
miguel sofer wrote: > On May 9, 7:48 pm, "Mikhail T." <mi+use @aldan.algebra.com> wrote: >> Hello! >> The Tcl's Tcl_SetFromAnyProc type is defined (in tcl.h) as: >> .... >> An actual implementation of the function is presumed to know, what the >> type is. However, in certain cases it may desirable to share the same >> function between different types. >> For that the function needs the third parameter: "const struct >> Tcl_ObjType *" and my question is: what's the best way to add it? >> ... >> Should the Tcl_SetFromAnyProc become a union of the old and the new >> function types? Any other ideas? > Why not leaving the API as is, and simply do something like > int SetFooFromAnyProc (Tcl_Interp *interp, Tcl_Obj *objPtr) > { > Tcl_ObjType *fooPtr = &fooType; > return GenericSetFromAnyProc(interp, objPtr, fooPtr); > }
One particular idea, that I'm trying to implement, is a kind of generic "type factory". Most special types out there consist of a name and a number, which is an index into some array: file1, socket11, sybase5. These types don't really need to reimplement the methods of their own, but are forced to do so by the current API. My factory would provide a function like Tcl_ObjType * Tcl_NewType(const char *name); It will return a pointer to a structure, where the function-fields (methods) will all be the same meta-functions, which will do the right thing knowing, which type they operate on... They just need to know the type :-/ -mi
Bruce Hartweg wrote: >> Should the Tcl_SetFromAnyProc become a union of the old and the new >> function types? Any other ideas? > what would this buy you?
Ability to share methods between multiple object types. To the point of being able to have a "type factory" -- a single function, which creates and registers a new type without the caller (re)implementing all methods on their own. > the SetFromAny proc is called when needed, how would it know which > flavor to call if the pointer could be to 2 different functions? > you would have to change all the core code as well as any extensions > and again I ask why?
No, the new core's SetFromAny would always call with three arguments (interp, obj, typePtr). The old compiled extensions will ignore the extra argument -- thus, presumably, avoiding the ABI breakage. Seeking advice on minimizing the API breakage and a confirmation of there being no ABI breakage are the reasons for cross-posting to comp.lang.c. > if you have type A and type B what possible benefit could a single > function give you?
If (some of) the methods of type A and type B are very similar (such as: parse the integer index and look into an array), unifying them -- while still distinguishing the types themselves -- can be quite beneficial... See my other follow-up in this thread for more. At the moment, my proposed type-factory can get by without the extra argument. The price is the run-time penalty of a hash table lookup (Tcl_GetObjType). Fortunately, this is not going to happen frequently, as the objects don't often lose their internal representation in a running program. Would've been even better, if this could be achieved without the lookup, hence this thread. Please, take a look at the prototype of the factory at: http://aldan.algebra.com/~mi/miType.c.html The prototype dispenses with the internal arrays found in many external types, and makes the string representation consist of two parts: typeName and the actual pointer to the custom data (as per the miType_FORMAT)... Thanks! -mi
|
 |
 |
 |
 |
|