do..while(0) c2hs 中类似函数的 C 宏包装器
do..while(0) function-like C macro wrapper in c2hs
我想在 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
我做错了什么?
我的目标是包装 PETSc 库的 CHKERRQ
宏,在 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)
{ return ( TestF1(c) ); }
return
的语法需要一个(可选的)表达式:您不能使用语句代替表达式。 do {} while (0)
是一个语句。
(C11, 6.8.6 Jump statements)
Syntax
return expression_opt ;
您可以改为使用:
int c_testF1(int x)
{ TestF1(c); }
正如我在评论中所说,这会起作用,但我不建议这样做,这是糟糕的编码风格。 ?:
可以在示例 TestF1
宏中使用(如另一个答案中所写)但它不能用于您的 CHKERRQ
实际用例(您可以将宏用于 PetscError
函数调用)。
请记住,#define
是文本替换。所以
{ return ( TestF1(c) ); }
变成
{ return ( do{if c==0 return 0;else return 1; } while(0) ); }
并且您既不能使用 do { .. } while()
也不能使用其他 return
语句作为 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 环境中可能不是很有用
我想在 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
我做错了什么?
我的目标是包装 PETSc 库的 CHKERRQ
宏,在 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)
{ return ( TestF1(c) ); }
return
的语法需要一个(可选的)表达式:您不能使用语句代替表达式。 do {} while (0)
是一个语句。
(C11, 6.8.6 Jump statements)
Syntax
return expression_opt ;
您可以改为使用:
int c_testF1(int x)
{ TestF1(c); }
正如我在评论中所说,这会起作用,但我不建议这样做,这是糟糕的编码风格。 ?:
可以在示例 TestF1
宏中使用(如另一个答案中所写)但它不能用于您的 CHKERRQ
实际用例(您可以将宏用于 PetscError
函数调用)。
请记住,#define
是文本替换。所以
{ return ( TestF1(c) ); }
变成
{ return ( do{if c==0 return 0;else return 1; } while(0) ); }
并且您既不能使用 do { .. } while()
也不能使用其他 return
语句作为 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 环境中可能不是很有用