代码之家  ›  专栏  ›  技术社区  ›  Lee Hambley

编写跨平台C++代码(Windows、Linux和Mac OSX)

  •  35
  • Lee Hambley  · 技术社区  · 14 年前

    这是我第一次尝试在C++中编写一些稍微复杂的东西,我试图构建一个共享库,我可以从Objtovi-C和.NET应用程序进行接口(好的,那部分稍后会出现……)

    我的密码是-

    #ifdef TARGET_OS_MAC
      // Mac Includes Here
    #endif
    
    #ifdef __linux__
      // Linux Includes Here
      #error Can't be compiled on Linux yet
    #endif
    
    #ifdef _WIN32 || _WIN64
      // Windows Includes Here
      #error Can't be compiled on Windows yet
    #endif
    
    #include <iostream>
    
    using namespace std;
    
    bool probe(){
      #ifdef TARGET_OS_MAC
        return probe_macosx();
      #endif
      #ifdef __linux__
        return probe_linux();
      #endif
      #ifdef _WIN32 || _WIN64
        return probe_win();
      #endif
    }
    
    bool probe_win(){
      // Windows Probe Code Here
      return true;
    }
    
    int main(){
    
      return 1;
    }
    

    untitled: In function ‘bool probe()’:untitled:29: warning: control reaches end of non-void function

    5 回复  |  直到 13 年前
        1
  •  33
  •   Community CDub    8 年前

    我将介绍这个特定功能:

    bool probe() {
    #ifdef TARGET_OS_MAC
      return probe_macosx();
    #elif defined __linux__
      return probe_linux();
    #elif defined _WIN32 || defined _WIN64
      return probe_win();
    #else
    #error "unknown platform"
    #endif
    }
    

    以这种方式编写它,作为if-elif-else链,可以消除错误,因为如果没有有效的return语句或者没有命中#错误,就不可能编译。


    http://codepad.org/3PArXCxo 错误消息示例。只能使用特殊的预处理 接线员,就像我上面说的。


    suggested ),你可能想也可能不想那样做。这将取决于您的代码的细节,比如平台之间共享了多少,以及您(或您的团队)认为保持功能同步的最佳方式,以及其他问题。

    您可能希望有一个单独的配置头,它可以将所有不同的编译器和平台特定的宏转换为您所控制的已知和理解的宏。或者,您可以通过构建系统将-DBEAKS\u PLAT\u LINUX添加到编译器命令行中,以定义该宏(请记住,在宏名称中使用前缀)。

        2
  •  51
  •   stijn    14 年前

    而不是重复你自己写同样的“如果定义”。。。。一次又一次地,你最好在头文件中声明probe()方法,并提供三个不同的源文件,每个平台一个。这还有一个好处,即如果您添加了一个平台,则不必修改所有现有的源代码,只需添加新文件即可。使用生成系统选择适当的源文件。

    结构示例:

    include/probe.h
    src/arch/win32/probe.cpp
    src/arch/linux/probe.cpp
    src/arch/mac/probe.cpp
    

    警告是因为probe()不返回值。换句话说,三个ifdefs都不匹配。

        3
  •  5
  •   ereOn    14 年前

    TARGET_OS_MAC , __linux__ , _WIN32 _WIN64 是在编译代码时定义的。

    所以你的代码是:

    bool probe(){
    }
    

    这就是为什么编译器抱怨到达非void函数的结尾。根本没有 return 条款。


    另外,对于更一般的问题,以下是我在开发多平台/体系结构软件/库时的指导原则:

    避免特殊情况。尝试编写与操作系统无关的代码。

    当处理特定于系统的东西时,试着把东西包装成“不透明”的类。例如,如果您正在处理文件(Linux和Windows上的不同API),请尝试创建 File 类,该类将嵌入所有逻辑并提供公共接口,而不管操作系统是什么。如果某个操作系统上没有某个功能,就处理它:如果该功能对某个特定的操作系统没有意义,那么通常什么都不做就可以了。

    简而言之:越少越好 #ifdef

        4
  •  1
  •   T.E.D.    14 年前

    警告是因为如果没有任何定义是实际定义的,那么您就没有 return 返回 .

        5
  •  1
  •   Chang Hyun Park    12 年前

    除了上面未完成的选项之外,为了添加更多的内容,指令 __linux__ _WIN32 编译器知道 TARGET_OS_MAC 指令不是,这可以通过使用 __APPLE__ http://www.winehq.org/pipermail/wine-patches/2003-July/006906.html