您无法将指向包含std::string成员的结构的指针传递给msgrcv,这违反了接口合约。
传递给msgrcv的第二个参数需要指向一个缓冲区,该缓冲区具有足够的空间来存储struct { long mtype; char mdata[size]; };格式的'普通'C结构,其中size是msgrcv的第三个参数。
不幸的是,由于可能存在对齐问题,确定此缓冲区的大小可能取决于size,但您必须假定它不在提供此类接口的系统上。您可以使用标准的offsetof宏来帮助确定这个大小。
由于vector连续存储其组件,因此一旦知道缓冲区的大小,就可以调整char的vector大小,并使用它来保存缓冲区。使用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 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);
}换个角度来说,你只需要按照msgsnd接口的要求将数据打包到struct黑客兼容数据数组中。正如其他人指出的那样,它不是一个好的界面,但是对实现定义的行为和对齐关注点进行了修饰,应该这样做。
例如
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 msgbuf(data.size() + data_offset);
long mtype = MSG_ID;
const char* mtypeptr = reinterpret_cast(&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();
}
}