std::string
にメンバーを含む構造体へのポインターを渡すことはできませんmsgrcv
。これは、インターフェースコントラクトに違反します。
に渡される2番目のパラメーターは、サイズがの3番目のパラメーターでmsgrcv
ある形式の「プレーン」C構造体を格納するのに十分なスペースを持つバッファーを指す必要があります。struct { long mtype; char mdata[size]; };
msgrcv
残念ながら、このバッファのサイズの決定は、アライメントの問題の可能性があるために依存size
する可能性がありますが、この種のインターフェイスを提供するシステムではないと想定する必要があります。標準offsetof
マクロを使用して、このサイズを決定できます。
vector
ストアはそのコンポーネントを連続して格納するため、バッファーのサイズがわかれば、のサイズを変更しvector
、char
これを使用してバッファーを保持できます。を使用すると、手動でバッファリング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インターフェイスで必要とされるように、データをハック互換のデータ配列にパックする必要があります。他の人がポインタを持っているので、それは良いインターフェースではありませんが、実装で定義された動作と配置の懸念について詳しく説明すると、このようなものが機能するはずです。
例えば
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();
}
}