473,320 Members | 2,107 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,320 software developers and data experts.

Building extensibility into an API

I've been having a discussion with some folks here about the wisdom or
otherwise of "building extensibility into an API".

Consider your favorite function in one of your libraries, perhaps
void foo(int bar, char *baz);

Now maybe you think of some cool improvement to foo that you could make,
but this relies on being able to pass an additional parameter to foo.
You now have some unattractive choices:
1) change the signature of foo and break API compatability between
versions of the library
2) have a new function
foo_v2(int bar, char *baz, long double newparam);
and make foo a wrapper for foo_v2.
3) don't make the improvement.

Now, this dilemma would never have arisen if you'd "built extensibility
into the API" in the following way.

Each function you write takes an unused void * parameter. So foo starts
out as
void foo(int bar, char *baz, void *p);
and the last parameter should be NULL.

Now, consider extending the parameters of foo. You now use a
foo_v2_extra_params structure. Its first field encodes the additional
parameters, and the remaining fields are these parameters. Then version
2 of foo can do this:

void foo(int bar, char *baz, void *p)
{
/* define additional params as auto variables */
if(p)
/* process *p, set up extra args */
else
/* set additional params to defaults */
/* do stuff */
}

If foo improves again, the struct just gets enlarged, and the function
casts p appropriately before proceeding.

Have people here implemented something like this in the past? What do
you think of it as a solution to the "API extension" problem?

--
Red danger: http://www.mindszenty.org
Oct 27 '07 #1
9 1307

"Francis Johnson" <sp******@garbage.invalidwrote in message
news:sl*******************@nospam.com...
I've been having a discussion with some folks here about the wisdom or
otherwise of "building extensibility into an API".

Consider your favorite function in one of your libraries, perhaps
void foo(int bar, char *baz);

Now maybe you think of some cool improvement to foo that you could make,
but this relies on being able to pass an additional parameter to foo.
You now have some unattractive choices:
1) change the signature of foo and break API compatability between
versions of the library
2) have a new function
foo_v2(int bar, char *baz, long double newparam);
and make foo a wrapper for foo_v2.
3) don't make the improvement.
2.
VirtualAllocEx anyone?...

you know, maybe in the future, this too will be extended:
VirtualAllocXXX
and:
VirtualAllocHardCore
VirtualAllocExtreme
VirtualAllocTooTheMax

or maybe:
VirtualAllocReloaded
VirtualAllocRessurection
....

now, they have to merge some of these together into a more powerful
function:
VirtualAllocHardCoreExtremeTooTheMax

or something...

Now, this dilemma would never have arisen if you'd "built extensibility
into the API" in the following way.

Each function you write takes an unused void * parameter. So foo starts
out as
void foo(int bar, char *baz, void *p);
and the last parameter should be NULL.

Now, consider extending the parameters of foo. You now use a
foo_v2_extra_params structure. Its first field encodes the additional
parameters, and the remaining fields are these parameters. Then version
2 of foo can do this:
<snip>
>
If foo improves again, the struct just gets enlarged, and the function
casts p appropriately before proceeding.

Have people here implemented something like this in the past? What do
you think of it as a solution to the "API extension" problem?
syscall, ioctl, ...

4. or, how about, we encode all our arguments and data as a big string?...
then, on call, the API parses the string and figures out what is going on.

5. or, even more spiffy, how about we make each argument its own function
call.
so, we call a function telling the API we are sending something, and a call
for each arg, and then a call to indicate when we are done.

....

hmm, was trying to come up with ideas which were bizarre, but oddly enough,
these are actually useful (and I have made good use of them in the past).

4. works good when the other end of the API is some elaborate piece of
machinery (such as a compiler or interpreter).
5. works well when you are building something, such as in a physics library
or GUI framework.

--
Red danger: http://www.mindszenty.org
Oct 27 '07 #2
Francis Johnson wrote:
I've been having a discussion with some folks here about the wisdom or
otherwise of "building extensibility into an API".

Consider your favorite function in one of your libraries, perhaps
void foo(int bar, char *baz);

Now maybe you think of some cool improvement to foo that you could make,
but this relies on being able to pass an additional parameter to foo.
You now have some unattractive choices:
1) change the signature of foo and break API compatability between
versions of the library
Many times, backward compability is important, but in some cases the API
is simply broken, and there is no way to avoid fixing existing code,
unless you change the API. gets() is a prime example here.
2) have a new function
foo_v2(int bar, char *baz, long double newparam);
and make foo a wrapper for foo_v2.
If the existing code isn't broken, adding a new API, is the bets way
IMO, but instead of using a wrapper, the usual case involve duplicating
some code and providing a new independent function to ensure you don't
break existing code.
3) don't make the improvement.
On a complex system, it might not be an improvement... :)
--
Tor <bw****@wvtqvm.vw | tr i-za-h a-z>

My C page: http://www.pg2.moo.no/C/index.html
-include Win32 build of splint 3.1.2
Oct 28 '07 #3
On Oct 27, 3:27 pm, Francis Johnson <spamt...@garbage.invalidwrote:
I've been having a discussion with some folks here about the wisdom or
otherwise of "building extensibility into an API".

Consider your favorite function in one of your libraries, perhaps
void foo(int bar, char *baz);

Now maybe you think of some cool improvement to foo that you could make,
but this relies on being able to pass an additional parameter to foo.
You now have some unattractive choices:
1) change the signature of foo and break API compatability between
versions of the library
2) have a new function
foo_v2(int bar, char *baz, long double newparam);
and make foo a wrapper for foo_v2.
3) don't make the improvement.

Now, this dilemma would never have arisen if you'd "built extensibility
into the API" in the following way.

Each function you write takes an unused void * parameter. So foo starts
out as
void foo(int bar, char *baz, void *p);
and the last parameter should be NULL.

Now, consider extending the parameters of foo. You now use a
foo_v2_extra_params structure. Its first field encodes the additional
parameters, and the remaining fields are these parameters. Then version
2 of foo can do this:

void foo(int bar, char *baz, void *p)
{
/* define additional params as auto variables */
if(p)
/* process *p, set up extra args */
else
/* set additional params to defaults */
/* do stuff */

}

If foo improves again, the struct just gets enlarged, and the function
casts p appropriately before proceeding.

Have people here implemented something like this in the past? What do
you think of it as a solution to the "API extension" problem?
Microsoft likes to put the size of a structure argument into itself
as a version indicator. This has an advantage (for poor programmer)
of not having to have/use magic constants.

SOMESTUFF stuff;
ZeroMemory (&stuff, sizeof stuff);
stuff.cbSize = sizeof stuff;
/* ... */
CallFunctionExSoWhatIfItsExAlready (&stuff);

Because Microsoft cares.

Best regards,
Yevgen

Oct 28 '07 #4
ym******@gmail.com wrote:
>
Microsoft likes to put the size of a structure argument into itself
as a version indicator. This has an advantage (for poor programmer)
of not having to have/use magic constants.
DEC used to do that in OpenVMS (so I imagine H-P still does).
It didn't mesh well with C, though, and I once had to swat a bug
that the practice caused.

As I recall, the structure in question was an RMS ("file
system") control block of some kind. C didn't and doesn't have
a good construct for initializing such things in a way that's
"opaque" to the programmer, so VMS' library provided `const'
versions of the various control blocks, initialized with assorted
defaults. Your program set up its own control block by copying
the library's version and then filling in extra fields:

struct RMSthing cb = preInitializedRMSthing;
cb.this = 42;
cb.that = "foobar.txt";

The control block contained its own self-describing size field,
which got copied from the library to the program's version -- and
since both of them were `struct RMSthing' instances, all was well,
right?

Wrong. DEC introduced a new feature (I think it was in
support of what was then called the "High Sierra" CD-ROM format)
that involved expanding the RMSthing by a few bytes -- let's say
it went from 40 bytes to 48, although I don't recall the actual
numbers.

Alas, preInitializedRMSthing lived in a shared library (like
a "DLL" or ".so" in other systems). Our code, already compiled
and running in the field, had allocated 40 bytes for `cb' above,
and copied only 40 bytes into it from preInitializedRMSthing.
So far, so good -- but among those 40 bytes was the size field,
which advertised the control block as being 48 bytes long, not 40.
So when we used the block to tell VMS to do something, VMS looked
at the size field, said "Oh, goodie: it's a new-style RMSthing!"
and started messing around with the eight bytes past the end of
our control block ...

--
Eric Sosman
es*****@ieee-dot-org.invalid
Oct 28 '07 #5
<ym******@gmail.comwrote in message
On Oct 27, 3:27 pm, Francis Johnson <spamt...@garbage.invalidwrote:
>I've been having a discussion with some folks here about the wisdom or
otherwise of "building extensibility into an API".
Microsoft likes to put the size of a structure argument into itself
as a version indicator. This has an advantage (for poor programmer)
of not having to have/use magic constants.

SOMESTUFF stuff;
ZeroMemory (&stuff, sizeof stuff);
stuff.cbSize = sizeof stuff;
/* ... */
CallFunctionExSoWhatIfItsExAlready (&stuff);

Because Microsoft cares.
That's the way to do it. If you need make a function extensible, wrap the
parameters into a structure and pass a size in so you can extend it. The
fact that MS do it means the paradigm will be familiar to a large base of
programmers.

However it's not a good way of writing software. Filling out the struct will
be a grief to your caller. It's the best that can be done with C, and in
fact with most languages.

--
Free games and programming goodies.
http://www.personal.leeds.ac.uk/~bgy1mm

Oct 28 '07 #6
"Malcolm McLean" <re*******@btinternet.coma écrit dans le message de news:
cY*********************@bt.com...
<ym******@gmail.comwrote in message
>On Oct 27, 3:27 pm, Francis Johnson <spamt...@garbage.invalidwrote:
>>I've been having a discussion with some folks here about the wisdom or
otherwise of "building extensibility into an API".
Microsoft likes to put the size of a structure argument into itself
as a version indicator. This has an advantage (for poor programmer)
of not having to have/use magic constants.

SOMESTUFF stuff;
ZeroMemory (&stuff, sizeof stuff);
stuff.cbSize = sizeof stuff;
/* ... */
CallFunctionExSoWhatIfItsExAlready (&stuff);

Because Microsoft cares.
That's the way to do it. If you need make a function extensible, wrap the
parameters into a structure and pass a size in so you can extend it. The
fact that MS do it means the paradigm will be familiar to a large base of
programmers.

However it's not a good way of writing software. Filling out the struct
will be a grief to your caller. It's the best that can be done with C, and
in fact with most languages.
Unix has even worse solutions for similar but related issues:

int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

--
Chqrlie.
Oct 28 '07 #7
On Sun, 28 Oct 2007 17:43:57 -0000, "Malcolm McLean" wrote:
>That's the way to do it. If you need make a function extensible, wrap the
parameters into a structure and pass a size in so you can extend it. The
fact that MS do it means the paradigm will be familiar to a large base of
programmers.
More often MS uses different names, e.g. CreateWindowEx vs.
CreateWindow. BTW, from a C programmer's point of view the Windows API
is a relatively good API.
--
Roland Pibinger
"The best software is simple, elegant, and full of drama" - Grady Booch
Oct 28 '07 #8
"Roland Pibinger" <rp*****@yahoo.coma écrit dans le message de news:
47***************@news.utanet.at...
On Sun, 28 Oct 2007 17:43:57 -0000, "Malcolm McLean" wrote:
>>That's the way to do it. If you need make a function extensible, wrap the
parameters into a structure and pass a size in so you can extend it. The
fact that MS do it means the paradigm will be familiar to a large base of
programmers.

More often MS uses different names, e.g. CreateWindowEx vs.
CreateWindow. BTW, from a C programmer's point of view the Windows API
is a relatively good API.
That's a case of a glas half full or half empty. I as a C programmer
consider the Windows API to a relatively bad API.

--
Chqrlie
Oct 29 '07 #9
Charlie Gordon said:

<snip>
I as a C programmer
consider the Windows API to a relatively bad API.
Which just goes to show that it takes all sorts, since I think the Win32 C
API is not only very good indeed, but in fact the only part of Windows I
actually enjoy using.

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
Oct 29 '07 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

0
by: relaxedrob | last post by:
Hi All! I have been reading from this document in order to understand just what an extensibility element is: Web Services Description Language (WSDL) Version 2.0 Part 1: Core Language...
0
by: Jason | last post by:
I created an Excel Add-In using Extensibility. I made some methods public so the user can call them from VBA code. The question is, can I create overloaded versions of the method? Obviously I can...
4
by: Richard | last post by:
All, I have coded an Outlook automation Addin in C# and .NET. I created the project using the Extensibility wizard. The Addin installs and runs Ok on my machine. However I am unable to...
1
by: Sachin | last post by:
Is there a active forum on issues and discussion on Extensibility projects dealing with Office addins using .net? Thanks Sachin.
1
by: frenchyyy | last post by:
Hello, I'm developing an add-in for Word2003 and I have some troubles. I’m using VS .NET 2003 ->extensibility project. The add-in works fine with the first document in Word I create/open...
1
by: Brian Keating | last post by:
Hi there, any you may know in vs2005 (possibly early versions) that you can click on the propertys folder in the solution explorer then click on the settings tab and add a setting for your...
17
by: Nick | last post by:
I am doing some research into building web applications using Object Oriented techniques. I have found the excellent patterns section on the MSDN site, but other than that I cannot find any good,...
0
by: Bill Barker | last post by:
I wish to create a new com add-in for a msoffice product To do this I create a new project, selecting "Extensibility Projects" in the "Other Projects" dialog, however I only have "DataBase Project"...
0
by: Eric Davies | last post by:
The existing server extensibilities in modern DBMSs have been critical in our company's development of software products that improve database performance for certain scientific computing...
0
by: DolphinDB | last post by:
Tired of spending countless mintues downsampling your data? Look no further! In this article, you’ll learn how to efficiently downsample 6.48 billion high-frequency records to 61 million...
0
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
0
by: Vimpel783 | last post by:
Hello! Guys, I found this code on the Internet, but I need to modify it a little. It works well, the problem is this: Data is sent from only one cell, in this case B5, but it is necessary that data...
0
by: jfyes | last post by:
As a hardware engineer, after seeing that CEIWEI recently released a new tool for Modbus RTU Over TCP/UDP filtering and monitoring, I actively went to its official website to take a look. It turned...
1
by: PapaRatzi | last post by:
Hello, I am teaching myself MS Access forms design and Visual Basic. I've created a table to capture a list of Top 30 singles and forms to capture new entries. The final step is a form (unbound)...
0
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
0
by: Defcon1945 | last post by:
I'm trying to learn Python using Pycharm but import shutil doesn't work
1
by: Shællîpôpï 09 | last post by:
If u are using a keypad phone, how do u turn on JavaScript, to access features like WhatsApp, Facebook, Instagram....
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.