我正在编写一个独立于平台的套接字库。基本文件结构如下:
source directory
|_________________________
| | |
v v v
header.hpp win32 linux
| |
v v
source.cpp source.cpp
头文件包含所有操作系统通用的#include
。源文件是特定于#include
平台的库。
我已经构建了许多这样的项目,但我遇到了套接字的问题。因为我为函数参数指定了默认值,所以header.h
需要在头文件中使用的#defines
的特定于平台的库,比如SOCK_STREAM
、AF_INET
和SOMAXCONN
。
现在,我不想在我的头文件中使用#ifdef _WIN32
语句,因为我希望所有特定于平台的代码都在源文件中的单独文件夹中。
我是不是被困在了两难的境地?避免#ifdef #includes
和使用依赖报头的#defines
指定默认参数值是不是相互排斥?
发布于 2012-07-16 14:40:16
您可以通过在与平台无关的头文件中声明并在特定于平台的.cpp文件中适当定义的函数来检索默认参数。
或者,您也可以在独立于平台的头文件中将它们声明为外部常量,并在特定于平台的.cpp中适当地定义它们。
发布于 2012-07-16 14:28:17
您可以使用其他一些通常无效的默认值。然后,特定于平台的代码可以检测到这个特殊的默认值,并将该值替换为您实际希望它表示的值。
/* 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);
}
发布于 2012-07-16 15:05:30
在您的库中添加一个已转换为平台本机类型的抽象层。
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
)都是这样做的。
https://stackoverflow.com/questions/11506277
复制