`
weiyuhu
  • 浏览: 235847 次
  • 性别: Icon_minigender_1
  • 来自: 南京
社区版块
存档分类
最新评论

对__BEGIN_DECLS 和 __END_DECLS 的理解

阅读更多
在C语言代码中头文件中,充斥着下面的代码片段:

__BEGIN_DECLS
.....
.....
__END_DECLS


       #if defined(__cplusplus)
       #define __BEGIN_DECLS extern "C" {
       #define __END_DECLS     }
       #else
       #define __BEGIN_DECLS
       #define __END_DECLS


扩充C语言在编译的时候按照C++编译器进行统一处理,使得C++代码能够调用C编译生成的中间代码。

由于C语言的头文件可能被不同类型的编译器读取,因此写C语言的头文件必须慎重。

C++ compilers:

    C++ compilers require that functions be declared with full prototypes, since C++ is more strongly typed than C. C functions and variables also need to be declared with the extern "C" directive, so that the names aren't mangled.

ANSI C compilers:

    ANSI C compilers are not as strict as C++ compilers, but functions should be prototyped to avoid unnecessary warnings when the header file is #included.
non-ANSI C compilers:
    Non-ANSI compilers will report errors if functions are prototyped.

These complications mean that your library interface headers must use some C preprocessor magic in order to be usable by each of the above compilers.

下面以一种标准的写法来示例如何准确的写可以安全被各种编译器使用的C文件。

Here are the relevant portions of that file:

/* __BEGIN_DECLS should be used at the beginning of your declarations,
   so that C++ compilers don't mangle their names.  Use __END_DECLS at
   the end of C declarations. */
#undef __BEGIN_DECLS
#undef __END_DECLS
#ifdef __cplusplus
# define __BEGIN_DECLS extern "C" {
# define __END_DECLS }
#else
# define __BEGIN_DECLS /* empty */
# define __END_DECLS /* empty */
#endif

/* __P is a macro used to wrap function prototypes, so that compilers
   that don't understand ANSI C prototypes still work, and ANSI C
   compilers can issue warnings about type mismatches. */
#undef __P
#if defined (__STDC__) || defined (_AIX) \
        || (defined (__mips) && defined (_SYSTYPE_SVR4)) \
        || defined(WIN32) || defined(__cplusplus)
# define __P(protos) protos
#else
# define __P(protos) ()
#endif

These macros are used in "foo.h" as follows:

#ifndef _FOO_H_
#define _FOO_H_ 1

/* The above macro definitions. */
...

__BEGIN_DECLS
int foo __P((void));
int hello __P((void));
__END_DECLS

#endif /* !_FOO_H_ */

Note that the `#ifndef _FOO_H_' prevents the body of `foo.h' from being read more than once in a given compilation.

Feel free to copy the definitions of __P, __BEGIN_DECLS, and __END_DECLS into your own headers. Then, you may use them to create header files that are valid for C++, ANSI, and non-ANSI compilers.

Do not be naive about writing portable code. Following the tips given above will help you miss the most obvious problems, but there are definitely other subtle portability issues. You may need to cope with some of the following issues:

    * Pre-ANSI compilers do not always support the void * generic pointer type, and so need to use char * in its place.
    * The const and signed keywords are not supported by some compilers, especially pre-ANSI compilers.
    * The long double type is not supported by many compilers.

对应c++的libraries 时文件代码的相关解释如下:

Creating libraries of C++ code should be a fairly straightforward process, because its object files differ from C ones in only three ways:

   1. Because of name mangling, C++ libraries are only usable by the C++ compiler that created them. This decision was made by the designers of C++ in order to protect users from conflicting implementations of features such as constructors, exception handling, and RTTI.
   2. On some systems, the C++ compiler must take special actions for the dynamic linker to run dynamic (i.e., run-time) initializers. This means that we should not call `ld' directly to link such libraries, and we should use the C++ compiler instead.
   3. C++ compilers will link some Standard C++ library in by default, but libtool does not know which are these libraries, so it cannot even run the inter-library dependence analyzer to check how to link it in. Therefore, running `ld' to link a C++ program or library is deemed to fail. However, running the C++ compiler directly may lead to problems related with inter-library dependencies.

The conclusion is that libtool is not ready for general use for C++ libraries. You should avoid any global or static variable initializations that would cause an "initializer element is not constant" error if you compiled them with a standard C compiler.

There are other ways of working around this problem, but they are beyond the scope of this manual.

Furthermore, you'd better find out, at configure time, what are the C++ Standard libraries that the C++ compiler will link in by default, and explicitly list them in the link command line. Hopefully, in the future, libtool will be able to do this job by itself.
分享到:
评论

相关推荐

    JavaCC语法文件中文版 V2.0_静水71

    JavaCC语法文件中定义了几个关键的保留字和结构,例如EOF、IGNORE_CASE、JAVACODE、LOOKAHEAD、MORE、PARSER_BEGIN、PARSER_END、SKIP、SPECIAL_TOKEN、TOKEN、TOKEN_MGR_DECLS。这些关键字有特定的用途,比如PARSER...

    stdio.h文件.pdf

    8. **编译预处理**:文件中的`__BEGIN_DECLS`和`__END_DECLS`宏用于在C++环境中开启和关闭声明的namespace保护,确保与C++标准库的兼容性。 通过`stdio.h`,程序员能够方便地处理各种输入输出任务,包括读写文本...

    test-decls.rar_The Right Track

    A DeclarationContext holds a reference to a v8::Context and keeps track of various declaration related counters to make it easier to track if global declarations in the presence of interceptors behave...

    sys文件夹里面的头文件c代码类资源

    4. **cdefs.h**:包含了一些通用的定义和宏,比如`__BEGIN_DECLS`和`__END_DECLS`,用于在C++环境中正确地处理C语言的函数声明。 5. **fcntl.h**:提供了文件控制函数的声明,如`fcntl()`, 它可以用来改变文件描述...

    2.1 UE4反射分析-空AActor拆解

    为了深入理解,我们可以在代码编辑器(例如Visual Studio with Visual Assist插件)中对这个宏进行展开。 当第一次展开`GENERATED_BODY()`时,会得到如`CURRENT_FILE_ID___LINE___GENERATED_BODY`这样的临时字符串...

    Bytecode-Generator:这是一个Java程序,它为任何以小语法编写的程序生成字节码,其中包括语句,表达式,逻辑和条件构造以及循环

    字节码生成器 这是一个Java程序,它... program -> decls stmts end decls -> int idlist ; idlist -> id { , id } stmts -> stmt [ stmts ] cmpdstmt-> '{' stmts '}' stmt -> assign | cond | loop assign ->

    MFC 登录用户名和密码设计

    在类定义中,使用`//{{AFX_DATA_DECLS(MyDialog)}`和`//}}AFX_DATA_DECLS`包围的代码块内,添加如下代码: ```cpp afx_msg void OnBnClickedOk(); CString m_username; CString m_password; ``` `OnBnClickedOk`是...

    capnp_generic_gen:Capnproto 通用生成器

    有点基于 Clang 的 ASTVisitor 的工作原理,除了它使用虚拟方法,因为我懒得做“奇怪的重复模板”技巧来保存 vtable,因为模式往往不会那么大或经常解析 vtables 的性能访客类对任何人都有很大的不同。 基本上,...

    MiniC词法和语法定义1

    - `compound_stmt`:包含局部变量声明`local_decls`和语句列表`stmt_list`的大括号包裹的结构。 - `local_decls`:函数内部变量声明,可以是另一个`local_decl`或为空。 - `if_stmt`:if条件语句,可以有else子句...

    TopDownParser

    'begin' decls stmts 'end' decls --> [ 'int' idlist ';' ] [ 'real' idlist ';' ] [ 'bool' idlist ';' ] idlist --> id {',' id} stmts --> [ stmt [ stmts ] ] stmt --> assign | cond | loop | ...

    compiler_minijava:我对Java子集的编译器的实现

    我将遵循Aho等人在“编译器:原理,技术和工具”中给出的建议和步骤。 人对Java的一个子集。 我看过其他资料,例如Appel编写的Java中的Modern Compiler Implementation,但感到前者对所有相关概念给出了更详尽的...

    u_index_modify.rar_In Time

    Output registers encode semantic information in their name. Need to lookup a table built at decl time.Input registers are referred to by their semantic name rather ... Use the mapping build up the decls.

    postgresql 实现c language外部函数调用

    - 在编写C语言源代码时,可能需要包含PostgreSQL特定的头文件,如`postgres.h`、`fmgr.h`和`utils/geo_decls.h`,这些头文件定义了与PostgreSQL交互所需的函数和数据结构。 总的来说,通过C语言创建PostgreSQL外部...

    实验五_用语法制导方式生成中间代码生成器[收集].pdf

    yacc.y文件主要定义了语法规则,例如program、block、decls、statementlist等,并使用goto.c函数实现符号表、回填、创建节点、定义节点属性等功能。 五、实验结果 实验结果包括生成的中间代码序列和实验报告。实验...

    C++(Qt)软件调试-静态分析工具clang-tidy(18)

    C++(Qt)软件调试-静态分析工具clang-tidy是指使用clang-tidy对C++代码进行静态分析,以发现潜在问题和改进代码质量。clang-tidy是一个开源工具,支持C++/C/Objective-C语言,提供了一种基于AST(抽象语法树)的检查...

    哈工大编译原理课程报告

    报告中给出了文法(CFG)的一部分,如类型定义(int、float、bool、char)、声明(decls)和语句(stmts)等的词法规则。 2. **语法分析器**:这部分通常采用LR(1)分析法,对词法分析器输出的符号流进行解析,构建...

    tinypl-parser:这是一个递归下降解析器,用于使用Java为最小定义的编程语言语法生成JVM字节码。

    程序-> decls stmts结束decls-> int idlist; idlist-> id {,id} stmts-> stmt [stmts] cmpdstmt->'{'stmts'}' stmt->分配| cond | 环形分配-> id = expr; cond-> if'('rexp')'cmpdstmt [else cmpdstmt] 循环-> ...

    Gcc编译选项-报错告警选项.rar

    13. `-Wredundant-decls`:当代码中出现重复声明时发出警告。 在实际项目中,开发者通常会结合使用这些选项,以提高代码质量和可维护性。例如,`-Wall -Wextra -Werror`是一个常见的组合,它确保了代码不仅没有语法...

    向当前style sheet中插入一个新的style实现方法

    在网页开发中,有时我们需要动态地改变页面的样式,以...然而,需要注意的是,这种做法可能会增加页面加载时间和内存占用,因此在可能的情况下,还是建议将样式信息保留在独立的CSS文件中,以提高页面性能和维护性。

Global site tag (gtag.js) - Google Analytics