c code reusability

M

Michael Wojcik

Please use proper attribution lines (like the one above). I wrote the
twice-quoted text below.
I think is possible (and frequent) to have a new version of a existing
function with a new parameter in his signature.

An aside: the C language specification does not use the term
"signature", and I would recommend avoiding it when discussing C,
as it has a specific meaning in some languages (particularly ones
that support overloading) that is not applicable to C.
what way you propose to achieve such change mantaining
backward compatibility?

It depends on the function in question and the design of the library
interface, but in general I create a new function with one or more
additional parameters, and refactor the old function to call the
new function, with appropriate values for the new parameter(s) to
indicate that the old behavior should be used.

For example, say the first version of the library includes a
factory-pattern function for an ADT used by the library. The
interface might be something like:

struct XxxThing;
struct XxxThing *XxxCreateThing(void);

In the next version, I find it useful to have an enhanced factory
that performs some optional processing. The new interface is:

struct XxxThing;
enum XxxCTOption
{
XxxOPT_NONE = 0,
XxxOPT_SOMETHING,
XxxOPT_ANOTHER
};
struct XxxThing *XxxCreateThing(void);
struct XxxThing *XxxCreateThingEx(enum XxxCTOption Opt);

and in the implementation:

struct XxxThing *XxxCreateThing(void)
{
return XxxCreateThingEx(XxxOPT_NONE);
}

That's certainly not ideal - for one thing, it'd be better if the
name "XxxCreateThingEx" were more descriptive, but since this is
hypothetical I don't know what a "Thing" is or what the options
actually do - but it's a start. It'd be better if the original
XxxCreateThing had taken, say, a "void *Reserved" parameter which
could be used for other purposes in future versions.

--
Michael Wojcik (e-mail address removed)

Maybe, but it can't compete with _SNA Formats_ for intricate plot
twists. "This format is used only when byte 5, bit 1 is set to 1
(i.e., when generalized PIU trace data is included)" - brilliant!
 
M

Michael Wojcik

Michael said:
I wrote a fairly lengthy response to this, then decided I wasn't
sure what you're talking about. What's the antecedent of "that"?

But seriously, "that" referred to "[designing] libraries with a bit more
sense [...] thanks to reserved parameters, behavior flags, and so forth"; in
other words, forward compatibility on the function level. This technique is
rather brittle, and solves a problem (naming) that ought to have a cleaner
solution than changing around the semantics of existing code.

Perhaps it's been brittle in your experience. I've seen it used to
good effect in dozens of projects, and when used properly it does not
"chang[e] around the semantics of existing code". Indeed, that's
rather the point.

--
Michael Wojcik (e-mail address removed)

Unfortunately, as a software professional, tradition requires me to spend New
Years Eve drinking alone, playing video games and sobbing uncontrollably.
-- Peter Johnson
 
M

mister catering

CBFalconer said:
No, it is not possible. You create a new function with a different
name.
From the client's point is an evolution, not a new function. I think
the client will prefer to use the same name (of course, it won't be the
same implementation) because he is no more interested in the old
function. do you agree?

Another question is how to do it
 
M

mister catering

Michael said:
Please use proper attribution lines (like the one above). I wrote the
twice-quoted text below.

An aside: the C language specification does not use the term
"signature", and I would recommend avoiding it when discussing C,
as it has a specific meaning in some languages (particularly ones
that support overloading) that is not applicable to C.


It depends on the function in question and the design of the library
interface, but in general I create a new function with one or more
additional parameters, and refactor the old function to call the
new function, with appropriate values for the new parameter(s) to
indicate that the old behavior should be used.

For example, say the first version of the library includes a
factory-pattern function for an ADT used by the library. The
interface might be something like:

struct XxxThing;
struct XxxThing *XxxCreateThing(void);

In the next version, I find it useful to have an enhanced factory
that performs some optional processing. The new interface is:

struct XxxThing;
enum XxxCTOption
{
XxxOPT_NONE = 0,
XxxOPT_SOMETHING,
XxxOPT_ANOTHER
};
struct XxxThing *XxxCreateThing(void);
struct XxxThing *XxxCreateThingEx(enum XxxCTOption Opt);

and in the implementation:

struct XxxThing *XxxCreateThing(void)
{
return XxxCreateThingEx(XxxOPT_NONE);
}

That's certainly not ideal - for one thing, it'd be better if the
name "XxxCreateThingEx" were more descriptive, but since this is
hypothetical I don't know what a "Thing" is or what the options
actually do - but it's a start. It'd be better if the original
XxxCreateThing had taken, say, a "void *Reserved" parameter which
could be used for other purposes in future versions.

I think it'd be better to use a generic "void* import(char* function,
short version);" to get the desired function version (the returned
valud would need to be casted to the apropiate function pointer). OK,
is less efficient but think most times libraries "export" several
functions. One only import could get all the functions involved in a
new library version.

what do you think about this solution?
 
M

Michael Wojcik

I think it'd be better to use a generic "void* import(char* function,
short version);" to get the desired function version (the returned
valud would need to be casted to the apropiate function pointer).

The result of casting an object pointer to a function pointer type is
undefined. There is no generic function-pointer type; pointers to
functions with different parameter types are incompatible. So this
approach is not portable (though it will work on many implementations).

In any event, I don't care for it. I've yet to run across a case where
I had to create a new function similar to an existing one, and did not
want to give it a new name.

--
Michael Wojcik (e-mail address removed)

Be sure to push the button of the bottom, and push the button of the
settlement page indicated next only once, there is fear of the bottom
rhinoceros multiplex lesson money. -- Sukebe Net
 
B

Ben Pfaff

The result of casting an object pointer to a function pointer type is
undefined. There is no generic function-pointer type; pointers to
functions with different parameter types are incompatible. So this
approach is not portable (though it will work on many implementations).

But you can freely cast any function pointer to any other
function pointer type, so any function pointer type may be used
as a "generic" function pointer type. (You do need to invoke a
function through a compatible type.)
 
M

Michael Wojcik

But you can freely cast any function pointer to any other
function pointer type, so any function pointer type may be used
as a "generic" function pointer type. (You do need to invoke a
function through a compatible type.)

Argh. Right - I should have checked the standard before posting
that. I was thinking that the result of casting function pointers
wasn't defined, but per 9899-1999 6.3.2.3 #8 it is, just as you say.

So ignore my "not portable" comment above.

--
Michael Wojcik (e-mail address removed)

Advertising Copy in a Second Language Dept.:
Tapestry of the encounting and the farewell, the birth and the death.
You can hear the human being's song running through the 100 years.
-- Squaresoft
 
D

Dave Thompson

On 3 Sep 2006 16:35:24 GMT, (e-mail address removed) (Michael Wojcik)
wrote:
This argument is common (indeed, nearly universal) among the opponents
of dynamic linking, but it is entirely specious. On a typical modern
general-purpose OS, replacing all the dynamically-linked code with
statically-linked code would present a resource cost far in excess of
the "relative cheapness" of disk space and memory.

On one machine here in front of me, running Windows XP Pro, I
currently have 68 userspace processes running. 2192 DLLs are loaded
by them, from 358 distinct images, so on average an image is reused 6
times. The Windows loader isn't particularly smart, and is unable to
share an in- memory image if it's relocated; but I have only 58
relocations among those 2192, so the relocation rate is less than 3%.
The average size of a loaded DLL is 558 KB. So if we assume an even
distribution[1], the memory cost for DLLs on this system right now is
something like 358 * 1.03 * 558 KB = 200 MB. If they were statically
linked instead, the cost would be something like 2192 * 558 KB = 1194
MB, or about six times as much. I don't care to buy six times as
much RAM as I currently have installed, thank you very much. And the
disk space cost is worse.
Although (non-stupid) static linking only needs to include that
part(s) of a given library actually referenced by the given program,
which fraction would vary pretty widely but I would guess, totally off
the top of my head, might average something like 1/4 to 1/2 over a
largish population of programs like this. Plus on some targets, though
not I think x86, runtime-relocatable code aka PIC is larger though not
by anywhere near a factor of 2 and/or slower.

FWIW, my XP Home system32 has 1374 .dll files totalling ~280MB,
although probably most of them are never used, and progra~1 has about
twice as much of stuff installed with particular programs that are
almost certainly never shared -- if used at all, which many of my
OEM-installed alleged goodies aren't. But I consider this to reflect
M$Win and its culture much more than the linking method.

- David.Thompson1 at worldnet.att.net
 

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

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,066
Latest member
VytoKetoReviews

Latest Threads

Top