`
weiyuhu
  • 浏览: 231580 次
  • 性别: 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.
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics