Writing a buffer to a string

Hello everyone,
I have a problem with buffers. I need to send rootfiles through the net using CORBA. Therefore, I want to read the complete buffer, split it into several strings and then send it to a server or a client.
Anyways, I have a file f and I want to read its buffer into a string s. I can’t get it to work using the root manual, because I can’t find the exact command. (Writebuffer was the closest I got).



How far did you get? Which ‘buffer’ are you refering to?
What ‘characters’ are allowed in your string?


Maybe my terminology wasn’t right.
What I am trying to do is sending a root object through the internet using CORBA. I read the chapter about streamers which save the object to a file. They run through the whole class and save the variables to a buffer which is then written to a file. I need to access this buffer directly an copy it to a string to send it.
Since there is more to the whole project than this, I cannot use rootd or the apache web server.
Thats about how far I got. I saw the WriteBuffer functions in the manual, tried the WriteBuf functions of the bufferclass, but nothing really worked since I don’t know the right syntax. Most likely, a single function call like String = WriteThisFilesBufferToAString(file) would do it, but I can’t figure out this one.




Why do you want to write a ROOT object to a ROOT file
in order to send through the network via CORBA?
You can write the object to a TBuffer in memory,
send this buffer via Corba. On the other side,
read this object from TBuffer.
Note that we already have the neccessary classes (TSocket,
TMessage, etc) to send objects through the net.
In case you want to use a TBuffer, you can do something like:

TBuffer buf(TBuffer::kWrite); buf.WriteObject(myTObject*); or

then send the char* array pointed by buf.Buffer()
of length buf.Length().
In the calls above, myTObject* is a pointer to an object deriving
from TObject. myobj is a pointer to any object not deriving
from TObject, but instance of MyClass. myclass is a TClass* pointer
that you can obtain via

TClass *myclass = gROOT->GetClass("MyClass"); In both cases, your class must have a dictionary. If you do not know
how to make a dictionary, I suggest to use ACLIC like below.
Suppose that you have MyClass.cxx and MyClass.h, within ROOT, do

root > .L MyClass.cxx+ This will compile your class and make the dictionary automatically.
see also root.cern.ch/root/Dictionary.html


Hello Rene,
thank you so far. That’s exactly what I was searching for. Still, I have problems reproducing a class from the buffer.
I made a histogram and saved it to a file, writing the files buffer to buf.

[code]TH1F *h1 = new TH1F(“gaus”, “gaus”, 100, -4, 4);
h1->FillRandom(“gaus”, 1000);
TFile f;
f.Open(“hist.root”, “RECREATE”);
TBuffer buf(TBuffer::kWrite);

This works so far. But when I am using buf.Buffer(), the only output is @, because the second character of the string is ‘\0’. Is ‘\0’ a normal character in a buffer? The manual tells me, that the first 4 characters should be “root”.

When I am trying reproduce an Object, in this case a file, from the buffer, I am using

TClass *myclass = gROOT->GetClass("TFile"); buf.ReadObject(myclass);
which should return a pointer to a class instance reproduced according to the buffer. But root crashes when I am running this command.

buf.ReadObject(myclass); Fatal in <TBuffer>: IsReading() violated at line 2153 of 'base/src/TBuffer.cxx' aborting Generating stack trace... ...
What am I doing wrong?

The bigger picture of the project I am working on is to communicate with a running ROOT system via CORBA over the internet, to exchange data and to control certain processes running.



You should use:

TH1F *h1 = new TH1F("gaus", "gaus", 100, -4, 4); h1->FillRandom("gaus", 1000); TFile f; f.Open("hist.root", "RECREATE"); h1->Write(); f.Close(); TBuffer buf(TBuffer::kWrite); buf->WriteObject(h1);

TClass *myclass = gROOT->GetClass("TH!F"); buf.ReadObject(myclass);
Aka. Do not pass the TFile but pass the object you want to transfer.

[quote]Is ‘\0’ a normal character in a buffer?[/quote]Yes. This is a binary representation not an ascii representation.

[quote]The manual tells me, that the first 4 characters should be “root”. [/quote]This is the first character of a root file on disk. Not of the result of streaming a TFile object (which you attempted).


I still have the same problem passing the histogram instead of the file.

root [0] TH1F *h1 = new TH1F("gaus", "gaus", 100, -4, 4) root [1] h1->FillRandom("gaus", 1000) root [2] TFile f root [3] f.Open("hist.root","RECREATE") (class TFile*)0xa27fd08 root [4] h1->Write() (Int_t)417 root [5] f.Close() root [6] TBuffer buf(TBuffer::kWrite) root [7] buf->WriteObject(h1) root [8] TClass *myclass = gROOT->GetClass("TH1F") root [9] buf.ReadObject(myclass) Fatal in <TBuffer>: IsReading() violated at line 2153 of `base/src/TBuffer.cxx' aborting Generating stack trace... 0x401510b1 in TBuffer::ReadObjectAny(TClass const*) + 0x51 from /opt/root/lib/libCore.so 0x40151028 in TBuffer::ReadObject(TClass const*) + 0x14 from /opt/root/lib/libCore.so 0x402e0b99 in <unknown> from /opt/root/lib/libCore.so 0x40803a70 in G__ExceptionWrapper + 0x42 from /opt/root/lib/libCint.so 0x408be33a in G__call_cppfunc + 0x2c0 from /opt/root/lib/libCint.so 0x408ac318 in G__interpret_func + 0x890 from /opt/root/lib/libCint.so 0x4089819c in G__getfunction at v6_func.cxx:0 from /opt/root/lib/libCint.so 0x4092c078 in G__getstructmem + 0x9ec from /opt/root/lib/libCint.so 0x409235fb in G__getvariable at v6_var.cxx:0 from /opt/root/lib/libCint.so 0x4088dff0 in G__getitem at v6_expr.cxx:0 from /opt/root/lib/libCint.so 0x4088c896 in G__getexpr at v6_expr.cxx:0 from /opt/root/lib/libCint.so 0x408d821e in G__exec_function + 0xca from /opt/root/lib/libCint.so 0x408e0808 in G__exec_statement at v6_parse.cxx:0 from /opt/root/lib/libCint.so 0x40871be8 in G__exec_tempfile_core + 0x338 from /opt/root/lib/libCint.so 0x40871dda in G__exec_tempfile_fp + 0x22 from /opt/root/lib/libCint.so 0x408e9a88 in G__process_cmd + 0x5068 from /opt/root/lib/libCint.so 0x4020ed2e in TCint::ProcessLine(char const*, TInterpreter::EErrorCode*) + 0x13e from /opt/root/lib/libCore.so 0x40143321 in TApplication::ProcessLine(char const*, bool, int*) + 0x649 from /opt/root/lib/libCore.so 0x414a1dec in TRint::HandleTermInput() + 0x234 from /opt/root/lib/libRint.so 0x414a08e6 in TTermInputHandler::Notify() + 0x24 from /opt/root/lib/libRint.so 0x414a2268 in TTermInputHandler::ReadNotify() + 0x12 from /opt/root/lib/libRint.so 0x402ac196 in TUnixSystem::CheckDescriptors() + 0x148 from /opt/root/lib/libCore.so 0x402ab06a in TUnixSystem::DispatchOneEvent(bool) + 0x188 from /opt/root/lib/libCore.so 0x401c11ae in TSystem::InnerLoop() + 0x18 from /opt/root/lib/libCore.so 0x401c114e in TSystem::Run() + 0x7a from /opt/root/lib/libCore.so 0x40143b56 in TApplication::Run(bool) + 0x32 from /opt/root/lib/libCore.so 0x414a17a0 in TRint::Run(bool) + 0x410 from /opt/root/lib/libRint.so 0x08048d4b in main + 0x67 from /opt/root/bin/root.exe 0x41611ea0 in __libc_start_main + 0xd0 from /lib/tls/libc.so.6 0x08048c5d in TApplicationImp::ShowMembers(TMemberInspector&, char*) + 0x31 from /opt/root/bin/root.exe

Root crashes here.

But why should it work with TH1F, but not with a TFile? Both inherit from TObject.

When I am sending the string I get from buf. Buffer(), it includes the terminator symbol ‘\0’, which makes most string manipulation functions defined in string.h useless, since they stop after reaching the ‘\0’. Is there an elegant way around it or do I have to write my own routines, which don’t stop at a ‘\0’?



Humm … as hinted by the error message. The buffer is still in read mode (and position at the end of the stream). You need to add:

buf->SetWriteMode(); buf->Reset();before starting to read from the buffer.


Ok, buf->SetReadMode() did it.

Thank you very much for your help.



Sorry that’s indeed what I meant to write down :slight_smile: