CArchive::GetObjectSchema always returns -1

Posted on 1998-08-24
Last Modified: 2013-11-19
I'm trying to implement a serializable class with versioning, and I think I'm doing all the steps I'm supposed to: my class is declared with DECLARE_SERIAL, and it's defined with IMPLEMENT_SERIAL, and the third arg to the IMPLEMENT_SERIAL macro is (VERSIONABLE_SCHEMA | 4), just as DevStudio help tells me. Yet in my Serialize method, when I call ar.GetObjectSchema(), it always returns -1.

What gives?
Question by:barrett
  • 5
  • 3
  • 2
  • +1

Expert Comment

ID: 1321223
(begin quote)

Calling this function is only valid when the CArchive object is being loaded (CArchive::IsLoading returns nonzero). It should be the first call in the Serialize function and called only once. A return value of (UINT)–1 indicates that the version number is unknown

(end quote)

Presumably your code looks something like (it should) :-

void CMyObject::Serialize(CArchive& ar)
  // <--- Point 2

  if (ar.IsLoading())    
    // <--- Point 1

    int nVersion = ar.GetObjectSchema();
    // get all the data goes here
  } else
    // save all the data goes here

Do you have code at Point 1 or point 2 that touches the object or the archive, if yes, this is why.


Author Comment

ID: 1321224
My code does look like your sample, and I don't have any code at Point 1 or Point 2. I am, however, using MsDev 4.1 (required for this project) and am worried that there might be a bug -- er, I mean, "issue" with that version.

This is happening is a derived (leaf) class, and the GetObjectSchema() call is happening after two doc classes (base and derived) and a view class (base for my class) have already read some stuff from the archive. Could this be my problem? Do I need to call GetObjectSchema from the very first class to touch the archive?

Author Comment

ID: 1321225
I just tried putting the GetObjectSchema call in the first doc class that touches the archive, and I get the same results...

Expert Comment

ID: 1321226
It shouldn't have to a be a base class (leaf's should be okay".  However I'm suspicious of "and a view class".  

I think you should only be reading from the Doc class tree and not from the view as well.  Who is calling the view class serialization function ?

Author Comment

ID: 1321227
Here's the call stack up to the class I'm trying to serialize:

OPView::Serialize(CArchive & {...}) line 1186
CChartView::Serialize(CArchive & {...}) line 665
OPOleServerDoc::Serialize(CArchive & {...}) line 208
CChartDoc::Serialize(CArchive & {...}) line 292
COleDocument::LoadFromStorage() line 751

CChartDoc derives from OPOleServerDoc, and OPView derives from CChartView (I didn't write this). None of the other three classes are defined IMPLEMENT_SERIAL with the VERSIONABLE_SCHEMA flag, so I'm wondering if maybe each class must be defined this way. Some of these aren't even defined with the IMPLEMENT_SERIAL macro.

Maximize Your Threat Intelligence Reporting

Reporting is one of the most important and least talked about aspects of a world-class threat intelligence program. Here’s how to do it right.


Author Comment

ID: 1321228
Er, I meant to say that CChartView derives from OPView...

Expert Comment

ID: 1321229
I recall reading somewhere many moons ago that the 'schema' thing was deprecated by Microsoft before anyone actually used it and is only there now for source compatability.  In my Serialize() members, I stick my own explicit version number in as the first item stored and ignore the Schema thing.

Expert Comment

ID: 1321230
Where did you read that warmcat ?  My (Microsoft Press) book doesn't say that and infact devotes quite a lot of space to it.

BTW your workround should work if implemented properly, I don't know what happens to existing files that user schema's though

Accepted Solution

dmunoz earned 100 total points
ID: 1321231
I use sucessfully SCHEMA serialization in my documents, but I rewrite a lot af thinks... for the problem your asking, I think this could be the solution:

after calling your base class serialization, add :

UINT schema=SerializeSchema (ar, RUNTIME_CLASS (CYourClass));

UINT schema is the variable that receive the schema while loading resource. It's the schema specific to your class.
you can test it in the "if (ar.IsLoading())" part of your serialization function.

to declare SerializeSchema function, do something like:

UINT CYourClass::SerializeSchema (CArchive &ar, CRuntimeClass *pClass)
  UINT schema=(ar.IsLoading ()) ? ar.GetObjectSchema () : (UINT) -1;
  return schema;

the trick is that the class need to be serialized, to enable the GetObjectSchema() function.
I write all of this a very long time ago, I hope I'm not saying something stupid. If my memory is fine, I think it should work.

Hope that help.


Author Comment

ID: 1321232
You rock, dmunoz -- this code works perfectly!

Expert Comment

ID: 1321233
Thank you :-))  I'm glad to help.
Something that could help you if you go longer in Serialization.
Schema number should be a 16b short, not a 32b int like it's describe in runtime library! So, be carefull not to use the 16 upper bits of your schema... this one took me hours to find... You can see why in ARCCORE.CPP, line 309. WORD (short) is the MFC way...

Have a nice development day.


Featured Post

Free Trending Threat Insights Every Day

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

Join & Write a Comment

Suggested Solutions

Title # Comments Views Activity
Replacement selected text 2 48
Whole sheet autoscrub still needed 19 44
isEverywhere  challenge 19 64
Window placement 17 65
Introduction: Load and Save to file, Document-View interaction inside the SDI. Continuing from the second article about sudoku.   Open the project in visual studio. From the class view select CSudokuDoc and double click to open the header …
Introduction: Displaying information on the statusbar.   Continuing from the third article about sudoku.   Open the project in visual studio. Status bar – let’s display the timestamp there.  We need to get the timestamp from the document s…
This video will show you how to get GIT to work in Eclipse.   It will walk you through how to install the EGit plugin in eclipse and how to checkout an existing repository.
This demo shows you how to set up the containerized NetScaler CPX with NetScaler Management and Analytics System in a non-routable Mesos/Marathon environment for use with Micro-Services applications.

743 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

10 Experts available now in Live!

Get 1:1 Help Now