Adding a function's argument while preserving the API compatibility?

M

Mikhail T.

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
 
M

miguel sofer

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);
}
 
B

Bruce Hartweg

Mikhail said:
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?
Thanks!

-mi

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
 
F

Flash Gordon

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));

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.
 
M

Mark Janssen

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
 
M

Mikhail T.

miguel said:
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
 
M

Mikhail T.

Bruce said:
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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,014
Latest member
BiancaFix3

Latest Threads

Top