我想在C函数中包装一个类似函数的C宏(然后用{#fun ... #}
块将它包装在Haskell中),但是c2hs
预处理器会在{do.. while(0)
上进行阻塞。 1}}语法;
这是代码:
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)
答案 0 :(得分: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环境中可能不是很有用
答案 1 :(得分:5)
{ return ( TestF1(c) ); }
return
的语法需要(可选)表达式:您不能使用语句而不是表达式。 do {} while (0)
是一个声明。
(C11,6.8.6跳转声明)
语法
return expression_opt;
你可以做的是改为:
int c_testF1(int x)
{ TestF1(c); }
正如我在评论中提到的那样可行,但我不建议这样做,这是错误的编码风格。 ?:
可以在示例TestF1
宏中使用(如另一个答案中所述),但它不能用于CHKERRQ
实际用例(您可以使用宏来表示PetscError
1}}函数调用虽然)。