Can use macros to solve this problem?

H

hierro

I have a list of functions (all with suffix T). For each one, I need
to implement the following:

FunctionT()
{
if (some_condition)
{
// do some conversion first
FunctionW();
// then do some processing
}
else
{
// do some conversion first
FunctionA();
// then do some processing
}
}

The condition check, conversion and processing is the same for all
functions. Any way to use macros to save all the hassle? Or perhaps
with function pointers as well?
 
?

=?ISO-8859-1?Q?=22Nils_O=2E_Sel=E5sdal=22?=

hierro said:
I have a list of functions (all with suffix T). For each one, I need
to implement the following:

FunctionT()
{
if (some_condition)
{
// do some conversion first
FunctionW();
// then do some processing
}
else
{
// do some conversion first
FunctionA();
// then do some processing
}
}

The condition check, conversion and processing is the same for all
functions. Any way to use macros to save all the hassle? Or perhaps
with function pointers as well?

Sounds like a good tine for learning about state machines ...
 
M

Michael Mair

Hi there,
I have a list of functions (all with suffix T). For each one, I need
to implement the following:

FunctionT()
{
if (some_condition)
{
// do some conversion first
FunctionW();
// then do some processing
}
else
{
// do some conversion first
FunctionA();
// then do some processing
}
}

The condition check, conversion and processing is the same for all
functions. Any way to use macros to save all the hassle? Or perhaps
with function pointers as well?

You can do this with macros:

--- File Tfunc.ct ---
#if defined FUNCNAME && defined RET_TYPE
#define CONCAT(A,B) A ## B
#define FUNCNAME_T(f) CONCAT(f, T)
#define FUNCNAME_W(f) CONCAT(f, W)
#define FUNCNAME_A(f) CONCAT(f, A)

#ifdef PARAM_LIST
RET_TYPE FUNCNAME_T(FUNCNAME) (PARAM_LIST)
#else
RET_TYPE FUNCNAME_T(FUNCNAME) (void)
#endif
{
if (some_condition)
{
// do some conversion first
#ifdef PARAM_LIST
FUNCNAME_W(FUNCNAME) (ARG_LIST);
#else
FUNCNAME_W(FUNCNAME) ();
#endif
// then do some processing
}
else
{
// do some conversion first
#ifdef PARAM_LIST
FUNCNAME_A(FUNCNAME) (ARG_LIST);
#else
FUNCNAME_A(FUNCNAME) ();
#endif
// then do some processing
}
}
#undef FUNCNAME_T
#undef FUNCNAME_W
#undef FUNCNAME_A
#else
#error FUNCNAME or RET_TYPE not defined
#endif
#undef FUNCNAME
#undef RET_TYPE
#ifdef PARAM_LIST
# undef PARAM_LIST
# undef ARG_LIST
#endif
---------------------

--- funcT.c ---------
#include "prototypes.h" /* prototypes for the A and W functions */

.....
#define FUNCNAME firstfun
#define RET_TYPE int
#include "Tfunc.ct"

#define FUNCNAME secondfun
#define RET_TYPE void
#define PARAM_LIST int a
#define ARG_LIST a
#include "Tfunc.ct"
.....
---------------------

However, this gets nasty when creating the corresponding headerfile
--- funcT.h ---------
.....
int firstfunT (void);

void secondfunT (int a);
.....
---------------------

I would not do this.


I'd rather consider a function pointer solution

typedef int (*AWfunptr)(int);
typedef struct {
AWfunptr Afunc;
AWfunptr Wfunc;
} AWpairing;

int TCall (AWpairing *aw, int arg)
{
if (some_condition)
{
// do some conversion first
(*aw->Wfunc)(arg);
// then do some processing
}
else
{
// do some conversion first
(*aw->Afunc)(arg);
// then do some processing
}
}

.....

Note: As the above snippets are not complete programs, I have
not tested them. Especially for the template solution (the one
with the macros), look at the preprocessor output to see whether
everything is as intended.
Apart from that: // are C++ or C99 style comments
Do not use them for C89 code.


Cheers
Michael
 
T

Tim Rentsch

I have a list of functions (all with suffix T). For each one, I need
to implement the following:

FunctionT()
{
if (some_condition)
{
// do some conversion first
FunctionW();
// then do some processing
}
else
{
// do some conversion first
FunctionA();
// then do some processing
}
}

The condition check, conversion and processing is the same for all
functions. Any way to use macros to save all the hassle? Or perhaps
with function pointers as well?

Assuming the T's, W's and A's are defined/called just as shown above,
it's easy:

#define T_FUNCTION(n) \
void n ## T( void ){ common_body( n ## W, n ## A ); }

static void
common_body( void (*w)( void ), void (*a)( void ) ){
if( some_condition ){
/* conversion_w here */
w();
/* processing_w here */
} else {
/* conversion_a here */
a();
/* processing_a here */
}
}

T_FUNCTION(foo)
T_FUNCTION(bas)
T_FUNCTION(etc)

If conversion_w is the same as conversion_a, and processing_w is the
same as processing_a, then the common_body function can be simplified
further:

static void
common_body( void (*w)( void ), void (*a)( void ) ){
/* conversion */
(* (some_condition ? w : a))();
/* processing */
}

Obvious changes if the functions take arguments and/or return non-void
results.
 
R

Rob Thorpe

I have a list of functions (all with suffix T). For each one, I need
to implement the following:

FunctionT()
{
if (some_condition)
{
// do some conversion first
FunctionW();
// then do some processing
}
else
{
// do some conversion first
FunctionA();
// then do some processing
}
}

The condition check, conversion and processing is the same for all
functions. Any way to use macros to save all the hassle? Or perhaps
with function pointers as well?

Can't you find a way to do:-

FunctionT()
{
// do some conversion first
if (some_condition)
{
FunctionW();
}
else
{
FunctionA();
}
// then do some processing
}

If the conversion steps are the same for all the functions?
It would make things a lot simpler.
 
H

hierro

Thanks everyone for the help. Still trying to digest your solutions.

I've simplified the problem actually. Actually the different functions
all have different argument lists and return types.

Eg:
int firstFuncT(int, int) --> int firstFuncA(int, int) or int
firstFuncW(int, int)
void secondFuncT(float) --> void secondFuncA(float) or void
secondFuncW(float)

Is it still possible to solve using your suggested methods?

One more thing, to answer Tim and Rob, yes, the conversion and
processing for the A functions are different from those for the W
functions. But across functions (eg: firstFuncT and secondFuncT
above), conversion and processing for A functions are identical.
Similarly for the W functions.

Actually what i'm doing here is to provide generic functions that'll
call the respective unicode or ansi functions in the windows API. For
example, DrawTextT will call DrawTextW or DrawTextA after checking for
OS versions during runtime. The T-functions will take in UTF-8 strings
(in addition to other arguments) and convert to UTF-16(unicode) or
codepage(ansi) before passing those arguments in the respective W or A
function. The processing is just some clearing up of memory.

And no, I can't use the MSLU due to some restrictions.
 
H

hierro

I've tried your macro method and it seems to work fine. Only problem
is my function is DrawText and in the windows API it's already defined
as follows:

#ifdef _UNICODE
#define DrawText DrawTextW
#else
#define DrawText DrawTextA
#endif

So I end up getting DrawTextAX, DrawTextAW and DrawTextAA from the
preprocessor output.

I've #undef DrawText to make it work. Is it a good idea?
 
T

Tim Rentsch

I've simplified the problem actually. Actually the different functions
all have different argument lists and return types.

Eg:
int firstFuncT(int, int) --> int firstFuncA(int, int) or int
firstFuncW(int, int)
void secondFuncT(float) --> void secondFuncA(float) or void
secondFuncW(float)

Is it still possible to solve using your suggested methods?

One more thing, to answer Tim and Rob, yes, the conversion and
processing for the A functions are different from those for the W
functions. But across functions (eg: firstFuncT and secondFuncT
above), conversion and processing for A functions are identical.
Similarly for the W functions.

Something like this should work:

#define T_FUNCTION(n,parameters,arguments) \
void n ## T parameters { \
if(some_condition){ \
PRE_W_STUFF \
n ## W arguments ; \
POST_W_STUFF \
} else { \
PRE_A_STUFF \
n ## A arguments ; \
POST_A_STUFF \
} \
}

#define PRE_W_STUFF /*whatever*/
#define POST_W_STUFF /*whatever*/
#define PRE_A_STUFF /*whatever*/
#define POST_A_STUFF /*whatever*/

T_FUNCTION( firstFunc, ( int a, int b ), ( a, b ) )
T_FUNCTION( secondFunc, ( float f ), ( f ) )


Add another parameter to vary the return type. ok?
 
M

Michael Mair

hierro said:
I've tried your macro method and it seems to work fine. Only problem
is my function is DrawText and in the windows API it's already defined
as follows:

#ifdef _UNICODE
#define DrawText DrawTextW
#else
#define DrawText DrawTextA
#endif

So I end up getting DrawTextAX, DrawTextAW and DrawTextAA from the
preprocessor output.

I've #undef DrawText to make it work. Is it a good idea?

Umh, if it already is in the API, I would not #undef it.
Or, if you cannot do without: #include the respective header
_after_ your own headers/function definitions. Only if
there is no choice, #undef it and afterwards #define it
again. As you only are getting DrawTextT, DrawTextA, and
DrawTextW, this should not interfere with anything else.

As I said: Using function pointers may be safer.


Cheers
Michael
 

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,997
Messages
2,570,239
Members
46,827
Latest member
DMUK_Beginner

Latest Threads

Top