Deserialization trouble

Hi everyone again,

I’m having some troubles with serialization and deserialization. I am trying to get an object with a pointer datamember serialized to restore then. Apparently, the stream contains enough information to restore it but I am only getting a null pointer in datamember of restored object. I have tested also with streamer marks ("//->") but in either case it doesn’t work. Further, I have checked that the Dict.cxx Streamer method contains the same code with or without streamer marks.

I’m working with ROOT v5.34.21

I’ve attached an example with a class with a TString* datamember and a Launcher to see this issue.

Thanks in advance,
Javier Delgado.

Header:

#pragma once

#include "TObject.h"
#include "TString.h"

class StreamerTest : public TObject {
	public:
		StreamerTest() : fDataMember(0) {}

		void SetDataMember(TString* dataMember) { fDataMember = dataMember; }
		TString* GetDataMember() { return fDataMember; }

	protected:
		TString* fDataMember;//->
		
	ClassDef(StreamerTest, 1);
};

Output:

<Object class="StreamerTest">
	<Version v="1"/>
	<Version v="1"/>
	<UInt_t v="0"/>
	<UInt_t v="50331648"/>
	<UChar_t v="4"/>
	<CharStar v="Test"/>
</Object>

Example.zip (4.41 KB)

Dear Javier,

Problem is with dictionary generation for your class.
You creates default dictionary kind, which does not work with TBufferXML.
You need to create LinkDef.h file, which contains:

#ifdef __CINT__
#pragma link C++ class StreamerTest+;
#endif

This file should be last argument in your Makefile when dictionary is generated:

$(TARGET)Dict.$(SrcSuf): $(TARGETHEAD)
        @echo "Generating dictionary $@..."
        @rootcint -f $@ -c $(MYINCLUDES) $^ LinkDef.h
        @sync

After this modification result of your macro looks like:

root [0] 
Processing Launcher.C...
<Object class="StreamerTest">
  <StreamerTest version="1">
    <TObject fUniqueID="0" fBits="3000000"/>
    <fDataMember>
      <Object class="TString">
        <UChar_t v="4"/>
        <CharStar v="Test"/>
      </Object>
    </fDataMember>
  </StreamerTest>
</Object>

Pointer to restored object: 0x2d37230
Pointer to DataMember object: 0x2d36bf0
root [1] .q

Also, when you are using “//->” kind of comments for data members,
this object must be created in the default constructor like:

class StreamerTest : public TObject {
   public:
      StreamerTest() { fDataMember = new TString; }
   protected:
      TString* fDataMember;//->
};

In your case I see no reason for that.

Regards,
Sergey

P.S. Sorry for late reply and Happy New Year!

Dear Javier,

I modify TBufferXML code in ROOT repository (master and 5-34-00 branches).
Now it should also support default kind of streamers.
Output will look like:

<Object class="StreamerTest">
  <Version v="1"/>
  <Version v="1"/>
  <UInt_t v="0"/>
  <UInt_t v="50331648"/>
  <Class v="TString"/>
  <string v="Test"/>
</Object>

New code also provides simplified representation of TString and std::string data.

Sergey

Sorry for delay and a lot of thanks Sergey. That solved my serialization issue, I hadn’t read anything about LinkDefs… Now I am dealing with templates functions and classes and its tricky solution, but its enough to my project.

Nevertheless, my issue started with TProof::Process using TSelector object as selector param and PoD environments. As I could see, this method sends the class name to slaves instead of serialized TSelector object when you are working with TProofPlayerRemote (PoD in my case). However, the design of my project allowed me to send (through AddInput) some required objects, keeping a clean design and being transparent to users.

Thanks for helping me and thanks also for the ROOT contribution.

Greetings,
Javier Delgado.