C++:如何在 header 文件中包含 Paillier.h
C++: How to include Paillier.h in a header file
我有一个 C++ class key_gen 有一些 paillier_ prvkey_t[=29 类型的数据成员=].问题是我不能在我的 header 文件中包含 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 header 包含到我的 header 文件中,当我 运行 代码时,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;
^
谁能告诉我如何解决这个问题?
当您告诉 C 或 C++ 编译器处理文件时,foo.cpp
,编译的第一阶段是预处理,它扩展宏,替换定义和扩展预处理器指令,例如 #include
.
早期,预处理器是一个单独的程序,它会即时生成输出:C 编译器本身并不知道 #include
,它看到的只是一个代码流.
如今,预处理器通常是编译器(gcc、MSVC 等)不可或缺的一部分,但您在命令行上指定的每个源文件的单流效果保持不变,您仍然可以访问编译器将预处理的输出生成为单个中间文件,以便您可以查看正在进行的翻译(gcc/g++ 的 -E 选项)。所以如果你写:
// 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
文件中,您需要防止这种重复。有两种常见的方法可以做到这一点。
- pragma 守卫
在 .h 文件的开头使用预处理器指令 #pragma,GNU C 和 C++ 编译器都能理解:
#pragma once
Pro:预处理器检测到 #include
语句中的重复项,因此不必重新读取文件。
缺点:大多数编译器使用包含文件的路径来执行此操作,因此
#include "../include/foo.h"
#include "foo.h"
可能都引用同一个文件,但在某些编译器上仍会产生重复。
- #ifndef 守卫
在 .h 文件的开头检查唯一预处理器符号的定义,如果未定义,则定义它
#ifndef PAILLIER_H
#define PAILLIER_H
并且在文件的最后
#endif // PAILLIER_H (comment is optional)
Pro:无论路径如何,都进行重复数据删除。
缺点:如果你的 guard 名称不够独特,可能会导致问题(我在一个项目中工作,有人在多个头文件中使用了 'HEADER')
缺点:预处理器仍然必须读取整个头文件才能找到#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 由于路径原因使您失败,您仍然会被覆盖。
我有一个 C++ class key_gen 有一些 paillier_ prvkey_t[=29 类型的数据成员=].问题是我不能在我的 header 文件中包含 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 header 包含到我的 header 文件中,当我 运行 代码时,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;
^
谁能告诉我如何解决这个问题?
当您告诉 C 或 C++ 编译器处理文件时,foo.cpp
,编译的第一阶段是预处理,它扩展宏,替换定义和扩展预处理器指令,例如 #include
.
早期,预处理器是一个单独的程序,它会即时生成输出:C 编译器本身并不知道 #include
,它看到的只是一个代码流.
如今,预处理器通常是编译器(gcc、MSVC 等)不可或缺的一部分,但您在命令行上指定的每个源文件的单流效果保持不变,您仍然可以访问编译器将预处理的输出生成为单个中间文件,以便您可以查看正在进行的翻译(gcc/g++ 的 -E 选项)。所以如果你写:
// 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
文件中,您需要防止这种重复。有两种常见的方法可以做到这一点。
- pragma 守卫
在 .h 文件的开头使用预处理器指令 #pragma,GNU C 和 C++ 编译器都能理解:
#pragma once
Pro:预处理器检测到 #include
语句中的重复项,因此不必重新读取文件。
缺点:大多数编译器使用包含文件的路径来执行此操作,因此
#include "../include/foo.h"
#include "foo.h"
可能都引用同一个文件,但在某些编译器上仍会产生重复。
- #ifndef 守卫
在 .h 文件的开头检查唯一预处理器符号的定义,如果未定义,则定义它
#ifndef PAILLIER_H
#define PAILLIER_H
并且在文件的最后
#endif // PAILLIER_H (comment is optional)
Pro:无论路径如何,都进行重复数据删除。 缺点:如果你的 guard 名称不够独特,可能会导致问题(我在一个项目中工作,有人在多个头文件中使用了 'HEADER') 缺点:预处理器仍然必须读取整个头文件才能找到#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 由于路径原因使您失败,您仍然会被覆盖。