C ++:如何在头文件中包含Paillier.h

时间:2015-06-01 18:28:41

标签: c++ cygwin

我有一个C ++类 key_gen ,它有一些 paillier_ prvkey_t 类型的数据成员。问题是我不能在我的头文件中包含paillier库(在c中写入)说 key_gen.h 。但是我可以使用

将它包含在我的 key_gen.cpp
extern "C"{
#include<paillier.h>
}

我正在使用cygwin来运行我的代码,我使用命令行如下:

g++ Key_Gen.cpp -L/cygdrive/c/cygwin/home/Win7/libpaillier -l:libpaillier.a -      
-lgmpxx -lgmp

当我在我的头文件中包含paillier标头时,cygwin会在运行代码时发出警报。

错误包含许多行,例如:

In file included from Key_Gen.h:13:0,
from Key_Gen.cpp:2:
/usr/local/include/paillier.h:63:3: note: previous declaration as ‘typedef   
struct paillier_pubkey_t paillier_pubky_t’} paillier_pubkey_t;
                                            ^

有人可以告诉我如何解决问题吗?

1 个答案:

答案 0 :(得分:2)

当你告诉C或C ++编译器处理文件foo.cpp时,编译的第一阶段是扩展宏的预处理,替换定义和扩展预处理器指令,例如#include

在早期,预处理器是一个单独的程序,它动态生成输出:C编译器本身不知道#include,它看到的只是一个代码流。< / p>

今天,预处理器通常是编译器(gcc,MSVC等)的组成部分,但是在命令行中指定的每个源文件的单流效果保持不变,您仍然可以访问编译器生成预处理的输出作为单个中间文件,以便您可以看到正在进行的翻译(-E选项为gcc / g ++)。所以,如果你写:

// Foo.h
int foo;

// Bar.cpp
#include "Foo.h"
int bar;
#include "Foo.h"

编译器看到的是一个连续的流:

/* "Bar.cpp" from command line */
// Bar.cpp
/* "Foo.h" from Bar.cpp:2 */
int foo;
/* end "Foo.h" */
int bar;
/* "Foo.h" from Bar.cpp:4 */
int foo;
/* end "Foo.h" */
/* end "Bar.cpp" */
  • 编译阶段不了解#include
  • 预处理器默认不对#include进行重复数据删除,因此多个包含产生重复。

如果您要将paillier.h添加到自己的.h文件中,则需要阻止此重复。有两种常见的方法可以做到这一点。

  1. pragma guard
  2. 在.h文件的开头使用预处理器指令#pragma,GNU C和C ++编译器都能理解:

    #pragma once
    

    Pro:预处理器在#include语句中检测到重复,因此不必重新读取文件。 Con:大多数编译器都使用include文件的路径来执行此操作,因此

    #include "../include/foo.h"
    #include "foo.h"
    

    可能都引用同一个文件,但在某些编译器上仍然会产生重复。

    1. #ifndef guard
    2. 在.h文件的开头检查唯一的预处理器符号的定义,如果没有定义,则定义它

      #ifndef PAILLIER_H
      #define PAILLIER_H
      

      并在文件的最后

      #endif // PAILLIER_H  (comment is optional)
      

      Pro:无论路径如何都重复数据删除。 Con:如果您的防护名称不够独特,可能会导致问题(我在一个有人在多个头文件中使用'HEADER'的项目上工作) Con:预处理器仍然必须读取整个头文件才能找到#endif。

      总结

      您可能还想添加以下内容,以便在C和C ++中包含文件时使文件正常工作

      #ifdef __cplusplus
      extern "C" {
      #endif
      
      // all your symbols etc here
      
      #ifdef __cplusplus
      }; // extern "C"
      #endif
      

      这将使您的头文件看起来像这样:

      #ifndef PAILLIER_H
      #define PAILLIER_H
      
      #ifdef __cplusplus
      extern "C" {
      #endif
      
      // original code here
      ...
      // end original code
      
      #ifdef __cplusplus
      }; // extern "C"
      #endif
      
      #endif // PAILLIER_H
      

      #pragma once
      
      #ifdef __cplusplus
      extern "C" {
      #endif
      
      // original code here
      ...
      // end original code
      
      #ifdef __cplusplus
      }; // extern "C"
      #endif
      

      ---编辑---

      没有理由你不能同时使用

      #pragma once
      #ifndef MYPROJECT_SOMETHING_H
      ...
      #endif
      

      这样一来,如果#pragma因路径原因而失败,那么你仍然可以接受。