3

我想在 C 函数中包装一个类似函数的 C 宏(然后用{#fun ... #}块将它包装在 Haskell 中),但是预处理器在语法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

我究竟做错了什么?我的目标是包装CHKERRQPETSc 库的宏,定义如下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)
4

2 回答 2

9

请记住,这#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 环境中可能不是很有用

于 2015-04-23T17:32:22.100 回答
5
{ return ( TestF1(c) ); }

的语法return需要(可选)表达式:您不能使用语句代替表达式。是do {} while (0)一个声明。

(C11,6.8.6 跳转语句)

句法

返回表达式_选择;

您可以做的是改用:

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

正如我在评论中所说,这可行,但我不建议这样做,这是不好的编码风格。?:可以在示例宏中使用TestF1(如在另一个答案中所写),但它不能用于您的CHKERRQ实际用例(尽管您可以将宏用于PetscError函数调用)。

于 2015-04-23T17:27:16.430 回答