Serialization of pointers with custom allocators
Hi! Is it possible to serialize a class A by pointer using a custom allocator? (Not the custom in-place allocator approach). I'm trying to serialize the (OpenCV) class IplImage. The class is used like this: IplImage* img = cvCreateImage(...); ... cvReleaseImage(&img); I've tried the following: template<class Archive> inline void load_construct_data(Archive & ar, IplImage * img, const unsigned int file_version){ ... IplImage* tmpImg = cvCreateImage(...); memcpy(img, tmpImg, sizeof(IplImage)); } But I get exceptions later, when releasing the loaded image. As far as I can tell, the image class data is identical before and after serialization, so I guess that the cvCreateImage/cvReleaseImage keep track of pointers somehow and things go bad when the ReleaseImage is called by a pointer not returned by the CreateImage function? Can the allocation of the IplImage used as input to load_construct_data be customized somehow? I also tried using an IplImage * & as input to load_construct_data: template<class Archive> inline void load_construct_data(Archive & ar, _IplImage * & img, const unsigned int file_version){ _IplImage* tmpImg = cvCreateImage(...); delete img; img = tmpImg; } But that screws up the (de)serialization. Any suggestions or thoughts anyone? // Anders Sundman
Try avoiding the default handling that serialization uses. template<class Archive> void save_image_ptr(Archive & ar, IplImage const * const iptr){ ar << binary_object(iptr, sizeof(IplImage)); } template<class Archive> void load_image_ptr(Archive & ar, IplImage * & iptr){ iptr = cvCreateImage(...); ar >> binary_object(iptr, sizeof(IplImage) } Robert Ramey Anders Sundman wrote:
Hi!
Is it possible to serialize a class A by pointer using a custom allocator? (Not the custom in-place allocator approach).
I'm trying to serialize the (OpenCV) class IplImage. The class is used like this:
IplImage* img = cvCreateImage(...); ... cvReleaseImage(&img);
I've tried the following:
template<class Archive> inline void load_construct_data(Archive & ar, IplImage * img, const unsigned int file_version){ ... IplImage* tmpImg = cvCreateImage(...); memcpy(img, tmpImg, sizeof(IplImage)); }
But I get exceptions later, when releasing the loaded image. As far as I can tell, the image class data is identical before and after serialization, so I guess that the cvCreateImage/cvReleaseImage keep track of pointers somehow and things go bad when the ReleaseImage is called by a pointer not returned by the CreateImage function?
Can the allocation of the IplImage used as input to load_construct_data be customized somehow?
I also tried using an IplImage * & as input to load_construct_data:
template<class Archive> inline void load_construct_data(Archive & ar, _IplImage * & img, const unsigned int file_version){ _IplImage* tmpImg = cvCreateImage(...); delete img; img = tmpImg; }
But that screws up the (de)serialization.
Any suggestions or thoughts anyone?
// Anders Sundman
Thank you for your prompt answer.
Unfortunately, that doesn't seem to work. It doesn't matter that I pass
a ref. to a pointer to the load_construct_data function. Since the
library function:
template
Try avoiding the default handling that serialization uses.
template<class Archive> void save_image_ptr(Archive & ar, IplImage const * const iptr){ ar << binary_object(iptr, sizeof(IplImage)); }
template<class Archive> void load_image_ptr(Archive & ar, IplImage * & iptr){ iptr = cvCreateImage(...); ar >> binary_object(iptr, sizeof(IplImage) }
Robert Ramey
Anders Sundman wrote:
Hi!
Is it possible to serialize a class A by pointer using a custom allocator? (Not the custom in-place allocator approach).
I'm trying to serialize the (OpenCV) class IplImage. The class is used like this:
IplImage* img = cvCreateImage(...); ... cvReleaseImage(&img);
I've tried the following:
template<class Archive> inline void load_construct_data(Archive & ar, IplImage * img, const unsigned int file_version){ ... IplImage* tmpImg = cvCreateImage(...); memcpy(img, tmpImg, sizeof(IplImage)); }
But I get exceptions later, when releasing the loaded image. As far as I can tell, the image class data is identical before and after serialization, so I guess that the cvCreateImage/cvReleaseImage keep track of pointers somehow and things go bad when the ReleaseImage is called by a pointer not returned by the CreateImage function?
Can the allocation of the IplImage used as input to load_construct_data be customized somehow?
I also tried using an IplImage * & as input to load_construct_data:
template<class Archive> inline void load_construct_data(Archive & ar, _IplImage * & img, const unsigned int file_version){ _IplImage* tmpImg = cvCreateImage(...); delete img; img = tmpImg; }
But that screws up the (de)serialization.
Any suggestions or thoughts anyone?
// Anders Sundman
try something like the following:
#include <fstream>
#include
Looking at this I might make one more small adjustment: Robert Ramey wrote:
try something like the following:
#include <fstream> #include
#include #include #include class _IplImage { public: friend boost::serialization::access; int roi, width, height, depth, nChannels; int imageSize; int * imageData; template<class Archive> void save(Archive & ar, const unsigned int version) const { ar << roi << width << height << depth << nChannels; ar << imageSize; ar << boost::serialization::binary_object(imageData, imageSize); } template<class Archive> void load(Archive & ar, const unsigned int version){ ar >> roi >> width >> height >> depth >> nChannels; ar >> imageSize; imageData = CreateImageData(roi, width, height, depth, nChannels, imageSize); ar >> boost::serialization::binary_object(imageData, imageSize); } BOOST_SERIALIZATION_SPLIT_MEMBER() };
main(int argc, char *argv[]){ const _IplImage i; { std::ofstream os("test"); boost::archive::text_oarchive oa(os); oa << i; } _IplImage new_i; { std::ifstream is("test"); boost::archive::text_iarchive ia(is); ia >> new_i; } // compare the new and old images }
This compiles w/o issue on my system.
Robert Ramey
Thank you for the tip and for all the time you have spent helping me. I really appreciate it. Since we use the IplImage from a 3:rd party library I would like to try every possible work-around before forking of the library source (and having to maintain it) by adding member functions. But in the end, I might be forced to do just that. In that case I'll try your solution bellow. For now, I'll keep working to find some workaround using free functions. Best Regards, Anders Sundman Robert Ramey skrev:
Looking at this I might make one more small adjustment:
Robert Ramey wrote:
try something like the following:
#include <fstream> #include
#include #include #include class _IplImage { public: friend boost::serialization::access; int roi, width, height, depth, nChannels; int imageSize; int * imageData; template<class Archive> void save(Archive & ar, const unsigned int version) const { ar << roi << width << height << depth << nChannels; ar << imageSize; ar << boost::serialization::binary_object(imageData, imageSize); } template<class Archive> void load(Archive & ar, const unsigned int version){ ar >> roi >> width >> height >> depth >> nChannels; ar >> imageSize; imageData = CreateImageData(roi, width, height, depth, nChannels, imageSize); ar >> boost::serialization::binary_object(imageData, imageSize); } BOOST_SERIALIZATION_SPLIT_MEMBER() };
main(int argc, char *argv[]){ const _IplImage i; { std::ofstream os("test"); boost::archive::text_oarchive oa(os); oa << i; } _IplImage new_i; { std::ifstream is("test"); boost::archive::text_iarchive ia(is); ia >> new_i; } // compare the new and old images }
This compiles w/o issue on my system.
Robert Ramey
participants (2)
-
Anders Sundman
-
Robert Ramey