以下のようにVC++でSharedMemoryを使ってクラスを複数プロセスで共有したいと思っていますが
cv::Mat* mat;のようなポインタを含むクラスの共有が上手くいかないで困っております.
なにか上手い方法をご存知の方がいましたらご指導いただけないでしょうか?
# Sender側のプログラムで読み込んだ画像(Test.jpg)をメモリ経由でReciever側のプログラムから読みたいと考えています
# 共通
class ShareData
{
public:
int hoge;
float pt[10];
cv::Mat* mat;
};
HANDLE SMhandle;
ShareData *data;
void init(){
SMhandle = CreateFileMapping((HANDLE)0xFFFFFFFF, 0,PAGE_READWRITE,0,sizeof(ShareData),"SMtest");
data = (ShareData*)MapViewOfFile(SMhandle, FILE_MAP_WRITE,0,0,sizeof(ShareData));
}
void close(){
UnmapViewOfFile(SMhandle);
CloseHandle(SMhandle);
}
# Sender側======================
void main(){
init();
cv::Mat img;
std::string filename("C:\\Test.jpg");
img = cv::imread(filename);
while(1){
data->hoge = 1;
data->mat = &img;
printf("address:%p\n",&img);
}
close();
}
# Reciever側======================
void main(){
init();
while(1){
printf("hoge=%d\n",data->hoge);
printf("mat=[%d,%d]\n",data->mat->cols,data->mat->rows);
printf("address:%p\n",data->mat);
}
close();
}
SharedMemoryでポインタを共有することはできません。
それは、プロセスAにとっての100番地と、プロセスBにとっての100番地が異なるためです。
上記のような構造体をSharedMemroy内に格納すると、matのデータとしてcv::Matオブジェクトへのポインタそのもの(メモリアドレス)が共有されることになります。しかし、メモリ自体を共有していないので、同じアドレスのデータはプロセスごとにことなり期待した通りの動作はしません。
一番簡単な方法は、SharedDataに実体をもたせてしまうことです。
つまり、
class ShareData { public: int hoge; float pt[10]; cv::Mat mat; };
こうしてしまうことです。
もし、cv::Matに対して何か抽象化しておく必要があるのであれば、それを考慮してシリアライズ・デシリアライズを行う必要があるでしょう。
画像など可変でもっと大きなデータについてはこういう風にはいかないと思うので、画像自体を別なSharedMemoryを作成して格納しておき、それの参照情報をSharedData構造体に格納しておけばよいかと思います。
つまり、送る側はこんな感じです。
class ShareData { public: int hoge; float pt[10]; std::string objectName; }; std::string objectName = 何か識別子; HANDLE hData = CreateFileMapping((HANDLE)0xFFFFFFFF, 0,PAGE_READWRITE,0, 必要なサイズ, objectName); void* buf = MapViewOfFile(hData, FILE_MAP_WRITE,0,0, 必要なサイズ); // bufにデータを流し込む SharedData data; // dataに情報を設定 data.objectName = objectName; SMhandle = CreateFileMapping((HANDLE)0xFFFFFFFF, 0,PAGE_READWRITE,0,sizeof(ShareData),"SMtest"); data = (ShareData*)MapViewOfFile(SMhandle, FILE_MAP_WRITE,0,0,sizeof(ShareData));
受取側はこの逆でいいでしょう。
何かの参考になれば。