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...
Free Tool: ZipGrep

ZipGrep is a utility that can list and search zip (.war, .ear, .jar, etc) archives for text patterns, without the need to extract the archive's contents.

One of a set of tools we're offering as a way to say thank you for being a part of the community.


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.


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 Tool: Path Explorer

An intuitive utility to help find the CSS path to UI elements on a webpage. These paths are used frequently in a variety of front-end development and QA automation tasks.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

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 …
Exception Handling is in the core of any application that is able to dignify its name. In this article, I'll guide you through the process of writing a DRY (Don't Repeat Yourself) Exception Handling mechanism, using Aspect Oriented Programming.
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.

830 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