2016-03-22 2 views
3

В моей среде разработки некоторые вызовы ioctl терпят неудачу в первый раз, если я снова вызываю то же ioctl, что и возвращение. Это связано с некоторыми проблемами синхронизации времени, связанными с оборудованием.Как вызвать функцию несколько раз внутри макроса в C?

Таким образом, мы будем в течение некоторого временного решения, как маскировка все ioctl одним MACRO, внутри этого MACRO вызывающему ioctl три раза.

но это MACRO сбор сбор ошибок. Пожалуйста, предложите некоторое решение для решения этой проблемы.

Пример кода

#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; 
} 

Ошибка компиляции

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); 
     ^
+0

Мы не можем использовать функцию для этой цели, так как одновременный доступ У вызовов может привести к вопросы. –

+3

Этот комментарий не имеет смысла, Хакким. Если использование функции может привести к одновременному доступу к вызовам ioctl, так что может быть макрос. Выражения могут выполняться только в функции. – Peter

+3

@HakkimAnsari Зачем вам нужен макрос? Почему вы не можете просто обернуть это нормальной функцией? Ваш комментарий действительно не вызывает чувства. Это выглядит как проблема [XY] (http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem). –

ответ

2

Ваш макрос раскрывается блок в кода, который не является выражение.

Почему бы просто не использовать встроенную функцию? Пример код:

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; 
} 

Хотя ioctl_wrapper() не нужен встраиваемый, это обычно считается лучше оставить работу по оптимизации для вашего компилятора (особенно современные). Если он думает, что ioctl_wrapper() не должен быть встроен, использование макроса для «принудительного включения» может быть не очень хорошей идеей.


Он вдруг мне приходит в голову, что существует другой чрезвычайно тривиальный подход:

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

Если возвращаемое значение одного из трех вызовов не -1, retval будет 1; В противном случае это будет 0.

+1

Почему 'extern', а не' static'? Я бы использовал 'static' и никогда' extern' с встроенной функцией. –

+0

@JonathanLeffler Кажется, что 'extern' или' static' в порядке. См. Http://stackoverflow.com/a/216546/5399734 –

+0

Синтаксически, да. Вы понимаете семантику «extern»? Это не прямолинейно. –

4

Я бы посоветовал использовать стиль макроса do-while, чтобы избежать проблем с futur. И чтобы решить вашу проблему, дать RetVal в качестве параметра:

#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) 

И ваш звонок будет:

IOCTL_WRAPPER(RetVal, 1, 2, 3); 
+0

Спасибо, его работа для меня –

Смежные вопросы