Common Routine To Call (Almost) Identical Functions

G

gamename

Hi,

I have 2 vendor libraries. One is for transmitting, the other
receiving data. Virtually all of the functions in either lib are
almost exactly alike in the way they're called. The only external
difference is the name has an "R" or an "S" in it.

ex
fooSGetBytes(bufa, buftemp);
fooRGetBytes(bufa, buftemp);

Several of my own support routines have logic on the send and receive
side that are also identical except that they're calling "R" functions
or "S" functions.

Is there any way to have 1 routine that calls either the "S" or "R"
functions depending on a parm passed by the user? Otherwise, I have
dozens and dozens of situations like this:

if(send)
fooSGetBytes()
else
fooRGetBytes()

In short, I would rather have something like

fnptr = fooSGetBytes
....lotsa code...
fptr()

Any ideas?

Thanks,
-T
 
E

Eric Sosman

gamename said:
Hi,

I have 2 vendor libraries. One is for transmitting, the other
receiving data. Virtually all of the functions in either lib are
almost exactly alike in the way they're called. The only external
difference is the name has an "R" or an "S" in it.

ex
fooSGetBytes(bufa, buftemp);
fooRGetBytes(bufa, buftemp);

Several of my own support routines have logic on the send and receive
side that are also identical except that they're calling "R" functions
or "S" functions.

Is there any way to have 1 routine that calls either the "S" or "R"
functions depending on a parm passed by the user? Otherwise, I have
dozens and dozens of situations like this:

if(send)
fooSGetBytes()
else
fooRGetBytes()

In short, I would rather have something like

fnptr = fooSGetBytes
...lotsa code...
fptr()

Why "something like" instead of "something exactly like?"
That is, a function pointer seems the perfect solution to your
problem. Or perhaps a struct containing several function
pointers, if you need to call several "related" functions:

struct funcFamily {
someType (*getBytes)(someArgs);
typeSome (*putBytes)(otherArgs);
...
};

const struct funcFamily SFuncs = {
fooSGetBytes, fooSPutBytes, ... };
const struct funcFamily RFuncs = {
fooRGetBytes, fooRPutBytes, ... };

...
myFunc(&SFuncs);
...
myFunc(&RFuncs);
...

void myFunc(const struct funcFamily *fam) {
...
fam->getBytes(...);
...
fam->putBytes(...);
...
}

The fundamental assumption here is that the corresponding
pairs of S and R functions really are *identical* in their
argument lists and return types. If they aren't, I don't see
how you can avoid tests at the call sites.
 
M

Malcolm McLean

gamename said:
Hi,

I have 2 vendor libraries. One is for transmitting, the other
receiving data. Virtually all of the functions in either lib are
almost exactly alike in the way they're called. The only external
difference is the name has an "R" or an "S" in it.

ex
fooSGetBytes(bufa, buftemp);
fooRGetBytes(bufa, buftemp);

Several of my own support routines have logic on the send and receive
side that are also identical except that they're calling "R" functions
or "S" functions.

Is there any way to have 1 routine that calls either the "S" or "R"
functions depending on a parm passed by the user? Otherwise, I have
dozens and dozens of situations like this:

if(send)
fooSGetBytes()
else
fooRGetBytes()

In short, I would rather have something like

fnptr = fooSGetBytes
...lotsa code...
fptr()
/*
send or receive data
Parmas: data - buffer for return on send
len - number of bytes to send
mode = 0 = receive, 1 = send
Returns: 0 on success, -1 on fail
*/
int talk(void *data, int len, int mode)
{
if(mode)
res = SGetBytes(data, len);
else
res = RGetBytes(data, len);
if(res != len)
return -1;
return 0;
}

You might want to take more drastic action on fail, such as aborting the
program, if that makes sense for your application. Also if the interface to
your SGetBytes type functions is a bit fiddly you might want to put the
iritating bits into the function start - eg if buffers have to be aligned
and a multiple of 8 bytes you could use a temporary allocated in the
function, giving a clean interface to your calling code.
 
J

jaysome

Hi,

I have 2 vendor libraries. One is for transmitting, the other
receiving data. Virtually all of the functions in either lib are
almost exactly alike in the way they're called. The only external
difference is the name has an "R" or an "S" in it.

ex
fooSGetBytes(bufa, buftemp);
fooRGetBytes(bufa, buftemp);

Several of my own support routines have logic on the send and receive
side that are also identical except that they're calling "R" functions
or "S" functions.

Is there any way to have 1 routine that calls either the "S" or "R"
functions depending on a parm passed by the user? Otherwise, I have
dozens and dozens of situations like this:

if(send)
fooSGetBytes()
else
fooRGetBytes()

In short, I would rather have something like

fnptr = fooSGetBytes
...lotsa code...
fptr()

Any ideas?

Thanks,
-T

Consider using function pointers. Here is an example that should get
you going:

#include <assert.h>
#include <stdio.h>

#define MAX_TEMPBUF_SIZE 256

typedef enum
{
TX,
RX,
NUM_DIRECTIONS
} direction_enum;

typedef void (*tx_rx_function_type)
(
const char *bufa,
char *buftemp
);

static void exucute_function
(
direction_enum direction,
const char *bufa,
char *buftemp
);
static void fooSGetBytes(const char *bufa, char *buftemp);
static void fooRGetBytes(const char *bufa, char *buftemp);

static const tx_rx_function_type TX_RX_FUNCS[NUM_DIRECTIONS] =
{
fooSGetBytes,
fooRGetBytes
};

int main(void)
{
int ii;
const char *BUFS[NUM_DIRECTIONS] =
{"This is the TX buf.", "This is the RX buf."};
char tempbuf[MAX_TEMPBUF_SIZE];
for ( ii = 0; ii < NUM_DIRECTIONS; ii++ )
{
/* wrapped in a function */
exucute_function(TX, BUFS[ii], tempbuf);
/* called directly */
TX_RX_FUNCS[ii](BUFS[ii], tempbuf);
}

/* uncomment the following to fire off an assert. */
/*exucute_function(NUM_DIRECTIONS, BUFS[0], tempbuf);*/

return 0;
}

static void exucute_function
(
direction_enum direction,
const char *bufa,
char *buftemp
)
{
assert((direction == TX) || (direction == RX));
TX_RX_FUNCS[direction](bufa, buftemp);
}

static void fooSGetBytes(const char *bufa, char *buftemp)
{
printf
(
"fooSGetBytes() called with arguments bufa=%p buftemp=%p\n",
(void*)bufa,
(void*)buftemp
);

printf("bufa string is \"%s\"\n", bufa);
}

static void fooRGetBytes(const char *bufa, char *buftemp)
{
printf
(
"fooRGetBytes() called with arguments bufa=%p buftemp=%p\n",
(void*)bufa,
(void*)buftemp
);
printf("bufa string is \"%s\"\n", bufa);
}

Best reagards
 
B

Barry Schwarz

Hi,

I have 2 vendor libraries. One is for transmitting, the other
receiving data. Virtually all of the functions in either lib are
almost exactly alike in the way they're called. The only external
difference is the name has an "R" or an "S" in it.

ex
fooSGetBytes(bufa, buftemp);
fooRGetBytes(bufa, buftemp);

Several of my own support routines have logic on the send and receive
side that are also identical except that they're calling "R" functions
or "S" functions.

Is there any way to have 1 routine that calls either the "S" or "R"
functions depending on a parm passed by the user? Otherwise, I have
dozens and dozens of situations like this:

if(send)
fooSGetBytes()
else
fooRGetBytes()

You could use an array of function pointers and pass the array index
to your function which would then call the library function using the
specified element of the array.

/* return type */ (*fooptr[]) (/*parameter types*/) =
{fooRGetBytes, fooSGetBytes};

fooptr[send]();
In short, I would rather have something like

fnptr = fooSGetBytes
...lotsa code...
fptr()


Remove del for email
 
G

gw7rib

Hi,

I have 2 vendor libraries. One is for transmitting, the other
receiving data. Virtually all of the functions in either lib are
almost exactly alike in the way they're called. The only external
difference is the name has an "R" or an "S" in it.

ex
fooSGetBytes(bufa, buftemp);
fooRGetBytes(bufa, buftemp);

Several of my own support routines have logic on the send and receive
side that are also identical except that they're calling "R" functions
or "S" functions.

Is there any way to have 1 routine that calls either the "S" or "R"
functions depending on a parm passed by the user? Otherwise, I have
dozens and dozens of situations like this:

If you're wanting to write pairs of new functions which are identical
apart from which of the -S- and -R- functions they call, then you
could try something along the lines of the following:

macmain.c:

#define name(before, after) three(before, letter, after)
#define three(before, let, after) join(before, let, after)
#define join(before, let, after) before##let##after

#define letter R

#include "macsub.c"

#define letter S

#include "macsub.c"

macsub.c:

int name(Test, main) (void) {
name(Test, sub1) ();
name(Test, sub2) ();
}

These will compile to give:

int TestRmain (void) {
TestRsub1 ();
TestRsub2 ();
}

int TestSmain (void) {
TestSsub1 ();
TestSsub2 ();
}

This may of course not be what you want, but it's a suggestion.
Hope it helps.
Paul.
 

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,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top