do..while(0) функционально-подобная оболочка макроса C в c2hs

Я хотел бы обернуть функциональный макрос C в функцию C (и, в свою очередь, обернуть его в Haskell с помощью {#fun ... #} блок), но c2hs Препроцессор дросселей на do.. while(0) синтаксис; вот код:

module TestMacro where
#c

#define TestF1(n) do{if n==0 return 0;else return 1; } while(0)

int c_testF1(int x)
{ return ( TestF1(x) ); }

#endc

и вот ошибка:

c2hs TestMacro.chs
c2hs: C header contains errors:

TestMacro.chs.h:6: (column 12) [ERROR]  >>> Syntax error !
  The symbol `do' does not fit here.

make: *** [main] Error 1

Что я делаю неправильно? Моя цель - завернуть CHKERRQ макрос библиотеки PETSc, определяемый следующим образом: petscerror.h(разбить на несколько строк для удобства чтения):

#define CHKERRQ(n)             
    do {if (PetscUnlikely(n)) 
        return PetscError(PETSC_COMM_SELF,__LINE__,PETSC_FUNCTION_NAME,__FILE__,n,PETSC_ERROR_REPEAT," ");} 
    while (0)

2 ответа

Решение

Помни что #define это замена текста. Так

{ return ( TestF1(c) ); }

становится

{ return ( do{if c==0 return 0;else return 1; } while(0) ); }

и вы не можете ни использовать do { .. } while() ни другой return операторы в качестве возвращаемых параметров (и скобки вокруг ìf - условия отсутствуют). Чтобы ваш макрос работал в этом месте, его можно просто определить как

#define TestF1(n)    ((n)==0 ? 0 : 1)

редактировать

Функция, которая использует CHKERRQ может выглядеть так

int my_chkerrq( int n )
{
     CHKERRQ(n);
     return( whatever_you_want_to_return_here );
}

но я бы предложил прямо назвать то, что CHKERRQ() звонки:

int my_chkerrq( int n )
{
     if (PetscUnlikely(n)) 
         return( PetscError(PETSC_COMM_SELF,__LINE__,PETSC_FUNCTION_NAME,__FILE__,n,PETSC_ERROR_REPEAT," ") );
     else 
         return( whatever_you_want_to_return_here );
}

Конечно, в обоих случаях __LINE__ а также __FILE__ заменяются теми из кода C и может быть не очень полезным в среде Haskell

{ return ( TestF1(c) ); }

Синтаксис return требует (необязательного) выражения: вы не можете использовать выражение вместо выражения. do {} while (0) это утверждение.

(C11, 6.8.6 операторы переходов)

Синтаксис

return expression_opt;

Вместо этого вы можете использовать:

int c_testF1(int x)
{ TestF1(c); }

Как я добавил в комментариях, это будет работать, но я не советую это делать, это плохой стиль кодирования. ?: может быть использован в примере TestF1 макрос (как написано в другом ответе), но он не может быть использован для вашего CHKERRQ реальный вариант использования (вы можете использовать макрос для PetscError хотя вызов функции).

Другие вопросы по тегам