Hakkim Ansari
Hakkim Ansari

Reputation: 119

How to call a function multiple times inside a macro in C?

In my development environment some of the ioctl calls are failing on the first time, if I am calling the same ioctl again then it returning success. This is because of some hardware related time synchronization issues.

So we are going for some temporary solution like masking all ioctl with one MACRO, inside that MACRO calling ioctl three times.

but that MACRO throws compilation error. Please suggest some solution to resolve this issue.

Sample Code

#include <stdio.h>

int func (int a, int b, int c)
{
    return -1;
}

#define IOCTL_WRAPPER(a,b,c)                    \
            {                                   \
                int i = 0, retval = 0;          \
                while (i < 3)                   \
                {                               \
                    retval = func (a, b, c);    \
                    if (retval != -1)           \
                    {                           \
                        break;                  \
                    }                           \
                    i++;                        \
                }                               \
                retval;                         \
            }

int main ()
{
    int RetVal = 0;

    RetVal = IOCTL_WRAPPER(1, 2, 3);

    if (RetVal != -1)
    {
        printf ("\n pass \n");
    }
    else
    {
        printf ("\n fail \n");
    }

    return 0;
}

Compilation Error

a.c: In function âmainâ:
a.c:9:13: error: expected expression before â{â token
             {                                   \
             ^
a.c:27:14: note: in expansion of macro âIOCTL_WRAPPERâ
     RetVal = IOCTL_WRAPPER(1, 2, 3);
          ^

Upvotes: 3

Views: 883

Answers (2)

nalzok
nalzok

Reputation: 16107

Your macro expands to a code block, which is not an expression.

Why not just use an inline function? Example code:

static inline int ioctl_wrapper(int a, int b, int c)
{
    int i = 0, retval = 0;
    while (i < 3)
    {
        retval = func (a, b, c);
        if (retval != -1)
        {
            break;
        }
        i++;
    }
    return retval;
}

Although ioctl_wrapper() is not necessary inlined, it's usually considered better to leave the optimisation job to your compiler(especially modern ones). If it thinks ioctl_wrapper() should not be inlined, using a macro to "force inline" may not be a good idea.


It suddenly occurs to me that there exists another extremely trivial approach:

retval = (func(a, b, c) + 1) || (func(a, b, c) + 1) || (func(a, b, c) + 1);

If the return value of one of the three calls isn't -1, retval would be 1; Otherwise, it'll be 0.

Upvotes: 2

Puck
Puck

Reputation: 2114

I would advise to use the do-while macro style to avoid futur problems. And to solve your problem, give the retVal as a parameter:

#define IOCTL_WRAPPER(retval, a,b,c)        \
        do {                                \
            int i = 0;                      \
            while (i < 3)                   \
            {                               \
                retval = func (a, b, c);    \
                if (retval != -1)           \
                {                           \
                    break;                  \
                }                           \
                i++;                        \
            }                               \
        } while(0)

And your call would be:

IOCTL_WRAPPER(RetVal, 1, 2, 3);

Upvotes: 4

Related Questions