代码之家  ›  专栏  ›  技术社区  ›  Joe Schneider

C++:平台相关类型——最佳模式[关闭]

  •  21
  • Joe Schneider  · 技术社区  · 16 年前

    我正在寻找一种模式来组织多个C++平台的头文件。

    我有一个wrapper.h文件,它应该在Linux和Win32下编译。

    这是我能做的最好的了吗?

    // defs.h
    
    #if defined(WIN32)
    #include <win32/defs.h>
    #elif defined(LINUX)
    #include <linux/defs.h>
    #else
    #error "Unable to determine OS or current OS is not supported!"
    #endif
    
    //  Common stuff below here...
    

    我真的不喜欢C++中的预处理器。有没有一个干净(理智)的方法来做得更好?

    6 回复  |  直到 16 年前
        1
  •  19
  •   SirDarius    16 年前

    您应该使用能够执行平台检查并生成适当的编译器标志和/或配置头文件的配置脚本。

    有几种工具可以执行此任务,如 autotools , Scons ,或 Cmake .

    在您的例子中,我建议使用CMake,因为它与Windows很好地集成,能够生成visualstudio项目文件以及Mingw makefile。

    下面是一个带注释的CMake示例(CMakeFiles.txt):

    # platform tests
    include(CheckFunctionExists)
    include(CheckIncludeFile)
    include(CheckTypeSize)
    include(TestBigEndian)
    
    check_include_file(sys/types.h  HAVE_SYS_TYPES_H)
    check_include_file(stdint.h     HAVE_STDINT_H)
    check_include_file(stddef.h     HAVE_STDDEF_H)
    check_include_file(inttypes.h   HAVE_INTTYPES_H)
    
    check_type_size("double"      SIZEOF_DOUBLE)
    check_type_size("float"       SIZEOF_FLOAT)
    check_type_size("long double" SIZEOF_LONG_DOUBLE)
    
    test_big_endian(IS_BIGENDIAN)
    if(IS_BIGENDIAN)
      set(WORDS_BIGENDIAN 1)
    endif(IS_BIGENDIAN)
    
    # configuration file
    configure_file(config-cmake.h.in ${CMAKE_BINARY_DIR}/config.h)
    include_directories(${CMAKE_BINARY_DIR})
    add_definitions(-DHAVE_CONFIG_H)
    

    因此,您必须提供一个config-cmake.h.in模板,cmake将对该模板进行处理,以生成包含所需定义的config.h文件:

    /* Define to 1 if you have the <sys/types.h> header file. */
    #cmakedefine HAVE_SYS_TYPES_H
    /* Define to 1 if you have the <stdint.h> header file. */
    #cmakedefine HAVE_STDINT_H
    /* Define to 1 if your processor stores words with the most significant byte
       first (like Motorola and SPARC, unlike Intel and VAX). */
    #cmakedefine WORDS_BIGENDIAN
    /* The size of `double', as computed by sizeof. */
    #define SIZEOF_DOUBLE @SIZEOF_DOUBLE@
    /* The size of `float', as computed by sizeof. */
    #define SIZEOF_FLOAT @SIZEOF_FLOAT@
    /* The size of `long double', as computed by sizeof. */
    #define SIZEOF_LONG_DOUBLE @SIZEOF_LONG_DOUBLE@
    

    我邀请您访问cmake网站以了解有关此工具的更多信息。

        2
  •  6
  •   mmmmmm    16 年前

    一种方法是将特定于操作系统的头放入不同的目录中,并通过-I标志将该目录传递给编译器来控制找到哪个目录。

    如果是你的话

    #include "defs.h"
    
        3
  •  4
  •   bta    16 年前

    使用预处理器本身并没有什么“坏”的。它的创建是有原因的,像这样的条件编译/包含是做得相当好的事情之一。

    关键是保持代码的可读性。如果你最后有很多 #ifdef WIN32 代码中的块,或者如果您发现自己在大量文件中这样做,这里有一些技巧可以稍微清理一下代码。

    1) 将条件包含移到单独的文件中。您的源文件将 #include <defs.h>

    2) 让makefile决定要包含的文件。同样,您的源文件 #包括<定义h> . 您的makefile将检测当前平台并添加 -iwin32 -ilinux 编译器选项字符串。这是我通常采用的方法。您可以在makefile内部或在配置阶段(如果您正在动态生成makefile)执行平台检测工作。我还发现,在以后添加对新平台的支持方面,这个选项是最简单的;它似乎可以最大限度地减少需要进行的更改。

    3) 如果您是在Linux系统上构建(意味着任何Win32代码都将由交叉编译器生成),您可以让构建脚本创建到相应头文件目录的符号链接。您的代码可以将目录引用为 #include <platform\defs.h>

        4
  •  2
  •   corsiKa    16 年前

    预处理器本身并不是一件坏事。它是一个强大的工具,就像许多其他开发工具一样。问题是你如何使用它?

    如果你使你的预处理清晰,有文档记录,并且合乎逻辑,那就完全不是问题了。当你开始玩一些难以理解的“聪明”把戏时,这就成了一个问题。

    defs.h 包括在所有文件中,在一个文件中执行特定于操作系统的逻辑。

        5
  •  1
  •   ssegvic    16 年前

    例如,假设我们需要在跨平台应用程序中从firewire相机获取图像。在不同的平台上实现这一点的方法完全不同。然后,有一个公共接口将放在CameraIeee1394.hpp中,并将两个依赖于平台的实现放在CameraIeee1394\u unix.cpp和CameraIeee1394\u w32.cpp中是有意义的。

    为特定平台准备makefile的脚本可以通过简单地检查文件名后缀自动忽略外部平台的源文件。

        6
  •  0
  •   Charles    16 年前

    我通常的解决方法是,首先创建一个标头来执行平台和编译器检测,例如:

    #define LIB_PLATFORM_WIN32 (1)
    #define LIB_PLATFORM_LINUX (2)
    
    #if defined(WIN32)
       #define LIB_PLATFORM LIB_PLATFORM_WIN32
    #elif defined(LINUX)
       #define LIB_PLATFORM LIB_PLATFORM_LINUX
    #endif
    

    现在你有了你的平台;然后可以在整个代码中使用自己的定义。

    例如,如果您想要一个独立于编译器的64位整数,可以使用

    #if LIB_COMPILER == LIB_COMPILER_MSVC
        #define int64   __int64
        #define uint64  unsigned __int64
     #else
        #define int64   long long
        #define uint64  unsigned long long
    #endif
    

    如果你把它组织得井井有条,那么保持它的干净和理智就不会有问题