[omniORB] Arrays as return values without _alloc() everytime?

Peter Fischer pfischer at ira.uka.de
Sat Feb 28 04:12:54 GMT 2004


Hi everyone,

I have a question about whether it is possible to write a method with an
array (fixed-
or variable- length shouldn't matter to this question) as a return
value.
As far as I have seen this is only portably possible with using the
method _alloc()
and iterating through the whole array (which could be huge!) and filling
in the
values.
Below is some example code which is an extract of the relevant parts of
my code (didn't try
whether the example as such works but the complete version it comes from
does).
What I want to do is to initialize the array in the private member
'mPicture' of the 'inf_i'
object only once in its constructor and then being able to return it as
often as desired
by 'mpic()' but without making an additional copy in the method mpic()
using 'Picture_alloc()' or
something like that. However, I suspect CORBA needs _alloc() to get
control over the data and
copying it over the network, but wanted to ask you whether this is true.

But I thougt:
"When mpic() returns the 'Picture_slice*' pointer, why CORBA only seems
to copy the whole array
over the network - and not just the adress in the *server's* adress
space, which is meaningless
to the client and should not be used by it (which it does, however, if
done like in the example
below of the first entry of the array - when this pointer points to an
additional copy of
mPicture made using Picture_alloc()? Why isn't CORBA able to do the same
when just returning the
ordinary pointer to mPicture whithout using Picture_alloc()?"
Is there is a way to tell CORBA (omniORB) to copy it directly from
mPicture?
Again, when I used Picture_alloc() in the method mpic() it worked
because then CORBA seemed to
be aware of copying the array over the network in the client adress
space, allocating it there
and simultanously deallocating it in the server adress space.
But its inefficient to always Picture_alloc() a new array, iterating the
whole array to copy it
in the newly allocated space and then return that newly allocated array.

Isn't there a way (like using C++ locally, what about the promised
Location transparency
CORBA promises) to maintain the array in the private member 'mPicture'
of the 'inf_i' object
and directly copying it over the net without the additional
Picture_alloc()-copying and 'for'
iteration?
Return by value also isn't supported for arrays by C++ which would be a
possible solution which,
however, would also make the inefficient copy of the (huge!) array on
the function call stack
which is wasting both time and memory.

So, please help: Is there an efficient solution for my problem?

Thanks in advance if you are so kind for reading this.

Greetings,

Peter.



Here comes the code:

Let's consider the following IDL fragment ():

 typedef octet Picture[3*320*200];

 interface inf {
 attribute Picture mpic;

 };

omniIDL generates (besides all the other stuff, the _alloc, _free etc.
methods) something like:

 class _impl_inf : public virtual omniServant
 {
 public:
       virtual Picture_slice* mpic() = 0;
   virtual void mpic(const Picture _v) = 0;

 }

and class 'POA_inf' from which I derive 'inf_i' and implement the
interface:

 class inf_i : public POA_inf, public
PortableServer::RefCountServantBase
 {
 public:
   inf_i();
   virtual ~inf_i() {}
   virtual Picture_slice* mpic();
   virtual void mpic(const Picture _v);
 private:
   Picture mPicture;
 }

 inf_i::inf_i() { //Initialize mPicture in the constructor by a for
loop}

 Picture_slice* inf_i::mpic()
 {
   return mPicture;
 }

 void inf_i::mpic(const Picture _v)
 {
   int sizeOf_v = sizeof(Picture) / sizeof(*_v);

   for( int counter = 0; counter < sizeOf_v; counter++ ) {
     mPicture[counter] = _v[counter];
   }
 }

then in client.cxx:

 int
 main (int argc, char **argv)
 {
 try {
 CORBA::ORB_var orb = CORBA::ORB_init(argc, argv);

 CORBA::Object_var obj = getObjectReference(orb);

 inf_var infref = inf::_narrow(obj);

 Picture pic;
 int sizeOfpic = sizeof(pic) / sizeof(*pic);

 for( int counter = 0; counter < sizeOfpic; counter++ ) {
 pic[counter] = 199;
 }

 //  setting internal array of infref to pic;
 infref->myRGBPic( pic );

 Picture_slice* testPic;

 testPic = infref->mpic();

 cout << "client.cxx.main().testPic: " << testPic[0] << endl; //
segmentation fault

 }







More information about the omniORB-list mailing list