TMessage not working as expected?

Dear ROOTers, I try the code below on ROOT 5.12 SLC4

TMessage test(kMESS_OBJECT);
TH1I *myhisto=new TH1I(“test”, “test”, 10, 0, 10);
//test.Reset();
test.WriteObjectAny(myhisto, myhisto->Class());
std::cerr << "class " <GetName() << std::endl;

It fails because test.GetClass() is NULL. Should it not return a pointer to TH1I::Class or sth related? Are there any special compiler options to enable ROOT’s RTTI in gcc? Thanks,

filimon

Hi,

to be able to read from a TMessage without having received it from a socket, do:

 TMessage m(kMESS_OBJECT)
 TH1I *h = new TH1I("test", "test ff", 10, 0, 10)
 m.WriteObject(h)
 m.SetReadMode()         // switch to read mode
 m.Reset()                    // reset internal pointers
 m.ReadClass()->GetName()   // read class and get name

Note that m.GetClass() is only set when a message has been received from a socket.

Cheers, Fons.

Thanks Fons, it works as you suggest. I have a more general question now. On the receiving end of a TSocket, ideally we want to reconstruct the types of the objects, essentially by downcasting to a derived class. I have seen several ways to identify the actual derived class but I am not sure which is more efficient. There is an additional problem with templates:
I have MyDerived1, MyDerived1, MyDerived2 derived from MyBase: public TNamed
C++ RTTI is useless from a short check I did because it assumes that MyDerived1, MyDerived1 are the same (but correctly resolves MyDerived1 form MyDerived2. The same applies for using IsA() member of these classes (I was surprised by this- am I doing something wrong maybe?).
The other 2 options remaining is either compare IsA()->GetName() or compare TObject->GetHash(). The first one could be potentially slow, the second one I am not sure and moreover it has the disadvantage that when the definition of the class changes so is the hash value and therefore you cannot rely on this for persistency, right? Is the Hash() calculated at runtime at each call or is it a static member of TClass? Thanks,

filimon

Note that the C++ RTTI is useless in this type of case, if the base class has no virtual table (neither that class nor any of its base has a virtual function).
… But you say that you derived from TNamed … so it should have been okay.
Do you have a simple example reproducing the problem?
Did you generate the dictionary for all your template instances?
Did you add ClassDef to all your classes?

Cheers,
Philippe

Hi Philippe,
it seems that the problem was exactly in the lack of ClassDef for the derived template classes. In more details:
I had originally ClassDef(Derived) in the derived template classes but got an error which I could not understand, about template parameter missing. Therefore I commented out the ClassDef. What works is to put ClassDef(Derived), where Type is the template parameter of the class. This is a naive mistake but I think I was also mislead by the template example in User’s Guide 5.14, page 269. Shouldn’t there be a ClassDef(MyClass1)? This would be equivalent to what I have and works perfectly now. If the example is working it is strange, because it does not work for me. Please let me know if there is any catch. cheers,

filimon

[quote] Shouldn’t there be a ClassDef(MyClass1)[/quote]A priori, no it should not. Can you send me an example reproduce the problem when you did not have the in the ClassDef?

Thanks,
Philippe

Hi Phillippe,
I will try to extract the specific part of code. If I cannot I will prepare an example. Thanks,

filimon

Hi Phillipe,
I think I located the source of error:
If one declares

name {
space {
template name::space::ClassName {
ClassDef(name::space::ClassName, 1)
};
};
};

gets an error like
error: `template class name::space::ClassName’ used without template parameters

and this can be fixed either by ClassDef(ClassName, 1) or ClassDef(name::space::ClassName, 1)

So it is actually an interaction with namespaces that does this. Agreed that in the example there are no namespaces but there is no explicit mentioning about the handling of this case and I believe that ClassDef(name::space::ClassName, 1) should be valid syntax. Anyway, as I said, both ways work.

I found the answer while experimenting with partially specialized classes. cheers,

filimon

[quote]and this can be fixed either by ClassDef(ClassName, 1) or ClassDef(name::space::ClassName, 1)
[/quote]The correct syntax is ‘ClassDef(ClassName, 1)’ :slight_smile:
The issue with ClassDef(name::space::ClassName, 1) is that you could also ‘mistype’ ClassDef(othername::space::ClassName, 1) which will lead to incorrect behavior … (in other word the part ‘name::space’ is here fully redundant and you risk mistyping the redundancy).

Cheers,
Philippe