包括具有一个头文件和独立源文件的特定于平台的库

Including platform-specific libraries with one header file and separate source files

本文关键字:于平台 平台 文件 独立 包括具 源文件 有一个      更新时间:2023-10-16

我正在编写一个独立于平台的套接字库。基本文件结构如下:

source directory
|_________________________
|            |            |
v            v            v    
header.hpp   win32        linux
             |            |
             v            v
             source.cpp   source.cpp

头文件包含任何跨操作系统通用的#include。源文件#include平台特定的库。

我已经构建了很多这样的项目,但我遇到了套接字的问题。因为我为函数参数指定默认值,所以header.h需要头文件中使用的#defines的特定于平台的库,如SOCK_STREAMAF_INETSOMAXCONN

现在,我不想在头文件中使用#ifdef _WIN32语句,因为我希望所有特定于平台的代码都在单独文件夹中的源文件中。

我基本上是夹在岩石和坚硬的地方之间吗?避免使用#ifdef #includes和使用依赖于标头的#defines指定默认参数值是否互斥?

您可以通过在独立于平台的标头中声明并在特定于平台的.cpp文件中适当定义的函数检索默认参数。

或者,您也可以在独立于平台的标头中将它们声明为外部常量,并在特定于平台的.cpp.

中适当地定义它们

您可以使用其他通常无效的默认值。然后,特定于平台的代码可以检测到这个特殊的默认值,并将该值替换为您实际希望它表示的值。

/* header */
int mysocket (int domain = -1, int type = -1, int protocol = 0);
/* implementation */
int mysocket (int domain, int type, int protocol) {
    if (domain == -1) domain = AF_INET;
    if (type == -1) type = SOCK_STREAM;
    // ...wrapper specific stuff for the platform...
    return ::socket(d, t, p);
}

另一种可能性是在原型中保留缺失的参数。

/* header */
int mysocket ();
int mysocket (int domain);
int mysocket (int domain, int type);
int mysocket (int domain, int type, int protocol);
/* implementation */
int mysocket () { return mysocket(AF_INET, SOCK_STREAM, 0); }
int mysocket (int d) { retrun mysocket(d, SOCK_STREAM, 0); }
int mysocket (int d, int t) { return mysocket(d, t, 0); }
int mysocket (int d, int t, int p) {
    // ...wrapper specific stuff for the platform...
    return ::socket(d, t, p);
}

在库中添加一个抽象层,该抽象层被转换为平台本机类型。

namespace MySocketLibrary
{
    enum SocketType
    {
        StreamSocket,
        DataGramSocket,
        RawSocket,
        // etc.
    }
}

对于我的平台特定的Win32实现,那么:

int translate_socket_type(const MySocketLibrary::SocketType socket)
{
    switch(socket)
    {
        case  MySocketLibrary::StreamSocket:
            return 1;
        // etc.
    }
}

很多库(如boost::asio)都这样做。