2012-07-16 57 views
3

我正在编写一个独立于平台的套接字库。基本文件结构是这样的:将平台特定的库包含在一个头文件和单独的源文件中

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

头文件包含的任何#include S中的跨操作系统普遍。源文件#include平台特定的库。

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

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

我基本上是坚持在一块石头和一个艰难的地方?是否避免#ifdef #includes并指定默认参数值与标头相关的#defines互斥?

回答

2

您可以通过通过了在你的平台无关的头声明,并在适当的平台特定的.cpp文件定义的函数检索它们让你的默认参数。

或者,您也可以在平台独立标头中将它们声明为extern consts,并在您的平台特定的.cpp中适当地定义它们。

2

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

/* 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); 
} 
+0

我喜欢第一个的想法,但我为其他用户提供了Doxygen文档,并且将默认参数的值设置为无效值可能无助于可读性。 第二个是个好主意。我现在就给一个镜头。不过,我想减少代码重复。 – Littlegator 2012-07-16 14:36:32

+0

@Littlegator:我试着将代码重复的数量降到最低。但是,您的文档应该仅使用默认参数记录单个API。我确信你想到了命名不同的常量(比如mySOCK_STREAM)的想法,并且使用这些参数已经超出了你的想法,但为了保持一致性,你必须在套接字库中复制几乎所有常量。无论如何,如果这是你的意图,Anon的想法不是一个坏方法。 – jxh 2012-07-16 14:57:55

1

在翻译为平台本机类型的库中添加一层抽象。

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)做到这一点。

+0

我同意参考boost :: asio是一个非常好的主意。 – 2012-07-16 15:19:24