Reputation: 331
I am in a bit of a pickle. I am using the boost::serialization in order to save/load a pointer from memory. The saving part, I have no issues. I was able to verify that the serialization class is able to save the pointer without any issue. As a side note, the pointer class is a custom class that I created.
Some background. I am using the wxwidgets library to create a GUI. I am using the latest version (v3.1.0). The object inherits from the wxGLCanvas class. Which requires a pointer to the parent window. The class is being used to draw a grid on the screen and the user can interact with the grid by placing geometry shapes (mainly squares, arcs, and lines). Each shape is its own class. Within my class, I have datatypes that specify the grid step size, the placement of the camera, the zoom level, and the geometry shape vectors. All of these are able to be saved. Note that my class does specify other data types as well but I am not saving these so they are irrelevant to the discussion. As a side note, the class in question is called modelDefinition
Now, we come to the load part of the class. My current implementation is as such:
void MainFrame::load(string filePath)
{
std::ifstream loadFile(filePath);
if(loadFile.is_open())
{
modelDefinition temp(this, wxPoint(6, 6), this->GetClientSize(), _problemDefinition, this->GetStatusBar());
//modelDefinition tempDefintion = (*_model);
boost::archive::text_iarchive ia(loadFile);
ia >> _problemDefinition;
ia >> temp;
temp.copyModel(*_model);
//*_model = temp;
//(*_model) = tempDefintion;
_model->Refresh();
}
}
Implementation of the copy function:
void copyModel(modelDefinition &target)
{
target.setGridPreferences(_preferences);
target.setEditor(_editor);
target.setZoomX(_zoomX);
target.setZoomY(_zoomY);
target.setCameraX(_cameraX);
target.setCameraY(_cameraY);
}
My idea is this, that I create a temporary variable and initialize it to the values that I need it to be. Currently, it is empty. Then, I will load the data into the temporary variable and then copy the needed data structures into my main variable. However, the program crashes at ia >> temp
. I am not sure why right now. I go into the debugger and I do not get access to the call stack after the crash. I have a feeling that it is crashing within the boost library. I did place a break point within the serialize function in modelDefinition and the program never made it.
I did come across this forum posting: Boost serialization with pointers and non-default constructor
To be honest, I am not too sure if it applies to me. I am trying to think of a way that does but so far I can not find any reason that applies to me.
Here is the declaraction of the modelDefinition constructor:
modelDefinition::modelDefinition(wxWindow *par, const wxPoint &point, const wxSize &size, problemDefinition &definition, wxStatusBarBase *statusBar) : wxGLCanvas(par, wxID_ANY, NULL, point, size, wxBORDER_DOUBLE | wxBORDER_RAISED)
par MUST have a value. Null values are not accepted. I did see that the forum post did override the load function and grabbed the values and passed them into the constructor of the class. However, in my case, par is a this
pointer and I am not able to serialize the function and load this
back into the program (besides, this
will change on every single function call). this
refers back to the parent window. And overriding the load function in a different namespace prevent me from passing this
into the function. So basically, that option is out of the water (unless I am missing something).
Again, since I can't pass in NULL into the wxGLCanvas constructor, this option is off the table:
modelDefinition _model = new modelDefinition();
modelDefinition::modelDefinition() : wxGLCanvas(NULL, 0)
And I believe that this option is also off the table since my parent window that would be associated with the canvas is in a different namespace:
template<class Archive>
inline void load_construct_data(
Archive & ar, modelDefintion * foo, const unsigned int file_version
){
double test;// There would be more after this but to simplify the posting, I am just throwing this in here.
ar >> test;
::new(modelDefintion)_model(this, test); // Yeah, I don't think that this is going to work here.
}
Again, this
would need to be pointing to the parent window, which I don't think that I have access to.
So right now, I am a little lost on my options. So far, I am thinking that I will continue to be working on the first case to see where the program is crashing.
Although, I could really use someone's help in solving this issue. How can I load back the data structure of a non-default constructor pointer where I cannot save the data from the inherited object (because modelDefinition inherits from wxGLCanvas data type and I am unable to save this data type)?
Yes, I am aware of the minimal example. It will take me sometime to create a minimal example. If the forum people need it to effectively come up with a solution, then I will do it and post here. But again, it will take time and could be rather long.
Upvotes: 2
Views: 323
Reputation: 392833
Yes, load/save construct data is the tool to deal with non-default constructibles.
Your problem is different: you need state from outside because you are trying to load objects that require the state during construction, but it never got saved in the first place. Had it been, you could re-create the parent window just like it existed during serialization.
The only "workaround" I can see here is to use global state (i.e. access it through (thread) global variables).
I do not recommend it, but you're in a pickle so it's good to think about workarounds, even bad ones
As soon as you salvaged your data from the old-style archives, I suggest serializing into a format that
Of course I don't know about the over-arching goal here, so I can't say which approach is more apt, but without context I'd always strife for separation of concerns, i.e. de-coupling the serialization from any UI elements.
Upvotes: 2