您不能将指针传递给包含 to 的std::string
成员的结构msgrcv
,这违反了接口协定。
传递给的第二个参数msgrcv
需要指向一个有足够空间的缓冲区来存储一个“普通”C 结构,struct { long mtype; char mdata[size]; };
其中 size 是第三个参数msgrcv
。
不幸的是,确定此缓冲区的大小可能取决于size
可能的对齐问题,但您必须假设它不在提供此类接口的系统上。您可以使用标准offsetof
宏来帮助确定此大小。
由于 avector
连续存储其组件,一旦您知道缓冲区的大小,就可以调整 a vector
of 的大小char
并使用它来保存缓冲区。使用 a可以减轻您手动缓冲vector
的义务。free
delete[]
你需要做这样的事情。
std::string RecvMessage()
{
extern size_t size; // maximum size, should be a parameter??
extern int MSGQ_ID; // message queue id, should be a parameter??
extern long MSG_ID; // message type, should be a parameter??
// ugly struct hack required by msgrcv
struct RawMessage {
long mtype;
char mdata[1];
};
size_t data_offset = offsetof(RawMessage, mdata);
// Allocate a buffer of the correct size for message
std::vector<char> msgbuf(size + data_offset);
ssize_t bytes_read;
// Read raw message
if((bytes_read = msgrcv(MSGQ_ID, &msgbuf[0], size, MSG_ID, 0)) < 0)
{
throw MsgRecvFailedException();
}
// a string encapsulates the data and the size, why not just return one
return std::string(msgbuf.begin() + data_offset, msgbuf.begin() + data_offset + bytes_read);
}
反之,您只需struct
按照 msgsnd 接口的要求将数据打包到与 hack 兼容的数据数组中。正如其他人指出的那样,它不是一个好的接口,但掩盖了实现定义的行为和对齐问题,这样的事情应该可以工作。
例如
void SendMessage(const std::string& data)
{
extern int MSGQ_ID; // message queue id, should be a parameter??
extern long MSG_ID; // message type, should be a parameter??
// ugly struct hack required by msgsnd
struct RawMessage {
long mtype;
char mdata[1];
};
size_t data_offset = offsetof(RawMessage, mdata);
// Allocate a buffer of the required size for message
std::vector<char> msgbuf(data.size() + data_offset);
long mtype = MSG_ID;
const char* mtypeptr = reinterpret_cast<char*>(&mtype);
std::copy(mtypeptr, mtypeptr + sizeof mtype, &msgbuf[0]);
std::copy(data.begin(), data.end(), &msgbuf[data_offset]);
int result = msgsnd(MSGQ_ID, &msgbuf[0], msgbuf.size(), 0);
if (result != 0)
{
throw MsgSendFailedException();
}
}