我正在编写一个独立于平台的套接字库。基本文件结构如下:
source directory
|_________________________
| | |
v v v
header.hpp win32 linux
| |
v v
source.cpp source.cpp
头文件包含在操作系统中通用的任何#include
。源文件#include
平台特定库。
我已经构建了许多像这样的项目,但是我遇到了套接字问题。因为我正在为我的函数参数指定默认值,header.h
需要头文件中使用的#defines
平台特定库,例如SOCK_STREAM
,AF_INET
和{{ 1}}。
现在,我不想在我的头文件中使用SOMAXCONN
语句,因为我希望所有特定于平台的代码都位于不同文件夹中的源文件中。
我基本上被困在一块岩石和一块坚硬的地方之间?是否避免使用#ifdef _WIN32
并指定与标头相关的#ifdef #includes
互斥的默认参数值?
答案 0 :(得分: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);
}
答案 1 :(得分:2)
您可以通过在平台独立标头中声明并在平台特定.cpp文件中正确定义的函数检索它们来获取默认参数。
或者,您也可以在平台独立标头中将它们声明为extern consts,并在您的平台特定.cpp中适当地定义它们。
答案 2 :(得分: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
)都这样做。