跨平台库究竟如何适用于不同的机器
How exactly cross platform libraries works for different machines
最近在学习C++网络方面的知识,发现boost.asio
是一个跨平台的库,然后想到这个库是跨平台的,因为Windows提供了不同的网络库,甚至 mac,
那么它的功能如何在不同的 machines 上工作,跨平台库是否为此目的创建自己的功能,或者它们包含不同 machine 逻辑的不同私有功能并提供 public 功能,然后在编译期间检查哪些 machine 代码正在编译,并使用 machines 定义的库更改我们编写的函数。
例如
//Operations for windows
Private void WindowsFunc
{ code }
//Operations for mac
Private void MacFunc
{ code }
//library's functions
Public void Do
{
//Performs different operations
//for different machines
If (windows)
WindowsFunc
else if (Mac)
MacFunc
}
可能是一个解决方案
这通常是使用特定于编译器的宏来完成的。例如,gcc
编译器定义了预处理器符号
__linux
于 Linux。因此,C 或 C++ 代码可以使用
#if __linux
编译Linux-特定代码。实际代码中没有任何内容 #define
是这样的。这是默认定义的,由 gcc
的 Linux 版本定义。 gcc
支持的其他平台上定义了类似的预处理器宏。其他编译器有类似的预定义宏。跨平台库的来源 assemble 他们检查这些宏的集合以编译特定于操作系统的代码。
另一种常见的方法是将特定于库的符号显式定义为库的构建指令或脚本的一部分。跨平台库附带的构建说明包括 运行 来自库包的适当脚本的说明,该脚本运行编译器并显式设置适当的预处理器符号,然后以这种方式使用。
通常,在现代 C++ 代码中不鼓励使用预处理器,而且要谨慎使用。在实践中,这是预处理器宏使用非常普遍的一个用例。
有几种可能的方法:
- 使用 ifdefs
char* doFoo(void){
#ifdef _WIN32
return "win32";
#elif ...
return ...;
#endif ...
}
优点是不需要太多设置。
缺点是,如果你做得太多,它会使代码混乱。
- 在不同的目录下有不同的实现。
作为文件夹结构:
root
|---->Other files
|---->windows implementation
| |->foo.c
|---->linux implementation
|->foo.c
|---->macos implementation
|->foo.c
然后您可以使用一些构建系统或自定义 shell 脚本来选择内容。
(伪代码)
if(OS==windows)
compileDirectory(windowsImpl);
else if(OS==linux)
compileDirectory(windowsImpl);
if(OS==macos)
compileDirectory(windowsImpl);
优点是,它不会使代码混乱,允许更好地添加新功能和某种抽象。
相反的是,它的设置可能非常复杂。
一般跨平台库都是分层实现的。
有 public 接口、通用代码和一组最小化的平台相关代码。
public 界面通常使用 #if defined(symbol)
检查来确定它 运行 在哪个平台上。它可能包括基于此的系统 headers,但更多时候会简单地转发声明它需要为特定平台 APIs(如果有的话)公开的任何符号。在某些情况下,header 只有图书馆会比这更进一步。
通用代码将包含最少的平台特定内容。它将尝试使用抽象来处理平台特定的东西;它可能 #include
平台特定的助手 headers,但代码在平台之间是通用的。
比如,它可能会使用 Native::RWLock
和 Native::RWLock::lock( mutex )
函数,这些函数是 typedef 和围绕平台特定类型的精简包装器。
每个平台的平台特定代码都不同。它可以在构建系统 NativeMutexImp_mac.cpp
中有条件地编译,或者包装在 #ifdef
块中,甚至两者都可以。
现在 header 只有库比这更容易泄漏。一些组织性较差的跨平台代码会混合特定于平台的代码,而不是到处都是代码。最后,性能要求可能需要 public header 文件中的一些泄漏平台特定代码。
但主要思想是您隐藏 OS API 用途,而您又用它来实现跨平台功能。
这可以使最终用户代码比原生代码更快 OS API 使用 if 你的 API 比原生代码更容易高效使用API 是的。优化是可替代的;更容易提高性能的代码在实践中实际上更快。
最近在学习C++网络方面的知识,发现boost.asio
是一个跨平台的库,然后想到这个库是跨平台的,因为Windows提供了不同的网络库,甚至 mac,
那么它的功能如何在不同的 machines 上工作,跨平台库是否为此目的创建自己的功能,或者它们包含不同 machine 逻辑的不同私有功能并提供 public 功能,然后在编译期间检查哪些 machine 代码正在编译,并使用 machines 定义的库更改我们编写的函数。
例如
//Operations for windows
Private void WindowsFunc
{ code }
//Operations for mac
Private void MacFunc
{ code }
//library's functions
Public void Do
{
//Performs different operations
//for different machines
If (windows)
WindowsFunc
else if (Mac)
MacFunc
}
可能是一个解决方案
这通常是使用特定于编译器的宏来完成的。例如,gcc
编译器定义了预处理器符号
__linux
于 Linux。因此,C 或 C++ 代码可以使用
#if __linux
编译Linux-特定代码。实际代码中没有任何内容 #define
是这样的。这是默认定义的,由 gcc
的 Linux 版本定义。 gcc
支持的其他平台上定义了类似的预处理器宏。其他编译器有类似的预定义宏。跨平台库的来源 assemble 他们检查这些宏的集合以编译特定于操作系统的代码。
另一种常见的方法是将特定于库的符号显式定义为库的构建指令或脚本的一部分。跨平台库附带的构建说明包括 运行 来自库包的适当脚本的说明,该脚本运行编译器并显式设置适当的预处理器符号,然后以这种方式使用。
通常,在现代 C++ 代码中不鼓励使用预处理器,而且要谨慎使用。在实践中,这是预处理器宏使用非常普遍的一个用例。
有几种可能的方法:
- 使用 ifdefs
char* doFoo(void){
#ifdef _WIN32
return "win32";
#elif ...
return ...;
#endif ...
}
优点是不需要太多设置。
缺点是,如果你做得太多,它会使代码混乱。
- 在不同的目录下有不同的实现。
作为文件夹结构:
root
|---->Other files
|---->windows implementation
| |->foo.c
|---->linux implementation
|->foo.c
|---->macos implementation
|->foo.c
然后您可以使用一些构建系统或自定义 shell 脚本来选择内容。
(伪代码)
if(OS==windows)
compileDirectory(windowsImpl);
else if(OS==linux)
compileDirectory(windowsImpl);
if(OS==macos)
compileDirectory(windowsImpl);
优点是,它不会使代码混乱,允许更好地添加新功能和某种抽象。
相反的是,它的设置可能非常复杂。
一般跨平台库都是分层实现的。
有 public 接口、通用代码和一组最小化的平台相关代码。
public 界面通常使用 #if defined(symbol)
检查来确定它 运行 在哪个平台上。它可能包括基于此的系统 headers,但更多时候会简单地转发声明它需要为特定平台 APIs(如果有的话)公开的任何符号。在某些情况下,header 只有图书馆会比这更进一步。
通用代码将包含最少的平台特定内容。它将尝试使用抽象来处理平台特定的东西;它可能 #include
平台特定的助手 headers,但代码在平台之间是通用的。
比如,它可能会使用 Native::RWLock
和 Native::RWLock::lock( mutex )
函数,这些函数是 typedef 和围绕平台特定类型的精简包装器。
每个平台的平台特定代码都不同。它可以在构建系统 NativeMutexImp_mac.cpp
中有条件地编译,或者包装在 #ifdef
块中,甚至两者都可以。
现在 header 只有库比这更容易泄漏。一些组织性较差的跨平台代码会混合特定于平台的代码,而不是到处都是代码。最后,性能要求可能需要 public header 文件中的一些泄漏平台特定代码。
但主要思想是您隐藏 OS API 用途,而您又用它来实现跨平台功能。
这可以使最终用户代码比原生代码更快 OS API 使用 if 你的 API 比原生代码更容易高效使用API 是的。优化是可替代的;更容易提高性能的代码在实践中实际上更快。