我有一个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;
^
有人可以告诉我如何解决问题吗?
答案 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
文件中,则需要阻止此重复。有两种常见的方法可以做到这一点。
在.h文件的开头使用预处理器指令#pragma,GNU C和C ++编译器都能理解:
#pragma once
Pro:预处理器在#include
语句中检测到重复,因此不必重新读取文件。
Con:大多数编译器都使用include文件的路径来执行此操作,因此
#include "../include/foo.h"
#include "foo.h"
可能都引用同一个文件,但在某些编译器上仍然会产生重复。
在.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因路径原因而失败,那么你仍然可以接受。