[omniORB] Idea on in-process execution

b.keeping@ic.ac.uk b.keeping@ic.ac.uk
Fri, 22 Jan 1999 14:47:30 GMT


Hi fellow omniORBers,

Although we're probably all busy trying out 2.7.0, I'd like to share
some ideas I've been trying out - and perhaps get some better ones in
return!

I am interested in making alternative implementations of Corba objects
available in-process at runtime. The mechanism I'm using for this
dynamic loading of shared objects. I have built an example based on
"eg1", the simplest in-process example provided with OmniORB.

My main program eg1load.cc is as follows:
----------------------------------------------------------------------
// eg1load.cc - This a shared object version by Ben Keeping
//          of example 1 used in Chapter 2 
//          "The Basics" of the omniORB2 user guide.
//
//          In this example, both the object implementation and the 
//          client are in the same process.
//
// Usage: eg1
//
#include <iostream.h>
#include <dlfcn.h>
#include "echo.hh"

#include "greeting.cc"

typedef CORBA::Object_var (*omserver) (CORBA::ORB_ptr orb,CORBA::BOA_ptr  boa);

int
main(int argc, char **argv)
{
  CORBA::ORB_ptr orb = CORBA::ORB_init(argc,argv,"omniORB2");
  CORBA::BOA_ptr boa = orb->BOA_init(argc,argv,"omniORB2_BOA");
  //load shared object implementing echo.
  void* temp=dlopen("./echo.so", RTLD_LAZY);
  if (!temp) {
    cerr<< dlerror();
    //    exit(1);
  };
  //Get a handle to the shared objects "init" routine, and call it.
  omserver echoinit=(omserver) dlsym(temp,"init");
  CORBA::Object_var obj=(*echoinit)(orb,boa);
  // It returns an object reference for our echo object.
  // In a real application this would usually be a factory object.
  Echo_ptr myobjRef = Echo::_narrow(obj);
  // Obtain an object reference.
  // Note: always use _this() to obtain an object reference from the
  //       object implementation.

  hello(myobjRef);

  CORBA::release(myobjRef);
  // Dispose of the object reference.

  return 0;
}
----------------------------------------------------------------------

The shared object echo.so is created by compiling echoso.cc which
follows:

----------------------------------------------------------------------
// Shared object server code extracted from the eg1 example by 
// Ben Keeping
#include "echo_i.cc"
// init routine which the client will call, passing its orb and boa
// and getting back an object reference.
extern "C" CORBA::Object_var init(CORBA::ORB_ptr orb,CORBA::BOA_ptr  boa) {
  // Create the object.
  Echo_i *echo = new Echo_i();
  echo->_obj_is_ready(boa);

  // Start the server: note - uses the nonblocking OmniORB version.
  // Without this we would need to do our own multithreading.
  boa->impl_is_ready(0,1);
  return echo;
}
----------------------------------------------------------------------

greeting.cc and echo_i.cc are unchanged from those in the example
directory.

Some changes were made to the dir.mk file to build the executable
eg1load and the shared object echo.so. "eg1load" and "echoso" were
added to the `all' list, and rules for shared object compilation and
linking added.

The IRIX version of these is:

CXXDEBUGFLAGS = -g  -mips4 -KPIC
CXXSOLINKOPTIONS = -shared -n32 -mips4 -KPIC
define CXXSharedObj
(set -x; \
 $(RM) $@; \
 $(CXX) -o $@ $(CXXSOLINKOPTIONS) $(IMPORT_LIBRARY_FLAGS) \
    $(filter-out $(LibSuffixPattern),$^) $$libs; \
)
endef

The rule for building echoso is then:

$(echoso): echoso.o $(CORBA_STUB_OBJS) $(CORBA_LIB_DEPEND)
	@(libs="$(CORBA_LIB)"; $(CXXSharedObj))

the "client", eg1load, is built just by compiling eg1load.cc given
above:

$(eg1load): eg1load.o $(CORBA_STUB_OBJS) $(CORBA_LIB_DEPEND)
        @(libs="$(CORBA_LIB)"; $(CXXExecutable))


The idea of all this is that if I have two alternative implementations
of "echo", I can specify at runtime which one I want to use. The
argument to dlopen doesn't have to be a literal string of course! For
the type of application I am interested in, it is important for the
objects to be defined in-process because I anticipate large, frequent
interactions.

I have used this mechanism successfully on Solaris and SGI
implementations. But I would like to know if there are
better/different ways of achieving the same thing?

Note: for Windows users, LoadLibrary and GetProcAddress can be used
instead of dlopen and dlsym.

Ben Keeping
Imperial College