| DMI Basics | Features Profile | DMI Client Interface | ScriptVar | DMI Server | Using DMI in C++ | DMI with CfgScript | DMI Server Objects | Subclassing | Delegates |

Dynamic Method Invocation (DMI) - is a core ACDK feature for integration of scripting, middleware and distributed computing, like COM+ and CORBA.

Content of this chapter:

     DMI versus IDL
     Component communication == Object methods
     C++ static, strong typed, early bind language
     Generic Interface
     Two ways of in COM+ and CORBA
     Two ways communication in ACDK
   Dynamic Method Invokation (DMI)
     Dynamic polymorph methods (multi-methods)
   DMI Clients and DMI Servers
     DMI Server
     DMI Clients
     DMI Client and Server Implementation combinations


 DMI versus IDL

In CORBA or COM an IDL (Interface Definition Language) is used to describe the communication interfaces of services.
The normal way to connect different language domains - for example C++ and Java - you
  • have to write the interface defintion in the IDL,
  • use a IDL compiler to generate stubs and proxies in Java and C++ and
  • implement the classes in Java/C++ derived from from the the generated stubs.

DMI uses another aproach:
  • Implement the ACDK C++ class or Java class in normal way
  • In case of C++ use acdkmc to generate DMI meta information, in case of Java do nothing.

In IDL you have to use high expensive 'round trip' engineering tools to keep IDL and language implementation in synchronized state.
With DMI the used language will be used to distill or query the interface definition, so no such tools are needed.

For some interfaces - like CORBA - a IDL distiller is available to generate IDL files for the origin DMI server class.

 Component communication == Object methods

The communication between components in ACDK is over the Objects methods, whereas every class/object is a component.

 C++ static, strong typed, early bind language

C++ - the implementation language of ACDK - is a strong typed language and early binding of the components. This has the effect, that at compile time the types of the communicating objects and the binary interfaces must be known. The interfaces are static.
This has many advantages:
  • Error checks at compile time and not at runtime
  • Good performance

But there is also disadvantages:
  • Difficult to embed C++ into scripting languages.
  • Not possible to explore and call interfaces at runtime
  • No generic bridges between middle ware is possible

 Generic Interface

Most scripting and interpreted languages has more generic interface.

  • source code can be loaded at runtime
  • Object code can be written at runtime
  • The number and types of arguments are checked at runtime.

 Two ways of in COM+ and CORBA

The major component technologies COM+ and CORBA provides both ways of communication:
  • static bind calls:
    CORBA: static skeleton/proxy COM+: concrete interfaces
  • dynamic bind calls:
    CORBA: Dynamic Interface Invocation & Dynamic Skeleton Interface (DII/DSI) COM+: Interface IDispatch
In COM+ and interface, which supports both ways of communication are called dual dispatched interfaces.

 Two ways communication in ACDK

ACDK provides also two ways to communicate with ACDK objects:
  • static bind calls: Normal C++ method calls
  • dynamic bind calls: Dynamic Method Invokation (DMI)

 Dynamic Method Invokation (DMI)

Every ACDK class has a DMI interface, defined in the namespace %nref[acdk::lang::dmi] and the class  acdk::lang::dmi::StdDispatch.

Here an example of usage of this interface:

  // static C++ version
  RStringBuffer sb = new StringBuffer("Hello");
  RString erg = sb->toString();
  // DMI vesion
  RObject sb = StdDispatch::New("acdk/lang/StringBuffer", (const char*)"Hello ");
  sb->invoke("append", (const char*)"ACDK");
  RString erg = sb->invoke("toString");

A mixture of static and dynamic method calls is also possible:

  // DMI vesion
  RStringBuffer sb = StdDispatch::New("acdk/lang/StringBuffer", 
                                                      (const char*)"Hello ");
  RString erg = sb->invoke("toString");

 Dynamic polymorph methods (multi-methods)

Calling a method in C++ uses static overloading:

class AClass
: extends acdk::lang::Object
  void foo(IN(RObject) obj);
  void foo(IN(RString) str);
RObject obj = new String("asdf");
RAClass acls = new AClass();
acls->foo(obj); // this class void foo(IN(RObject) obj);

Calling methods via DMI the arguments types will be evaluated at runtime. The DMI dispatcher tries to find the best matching method for the given runtime arguments:

acls->invoke("foo", inOf(obj)); // calls void foo(IN(RString) str);

 DMI Clients and DMI Servers

There are 2 sides of the DMI protocols:

 DMI Server

DMI Server provides Object functionality in the DMI conforming way.

  • All ACDK C++ Objects.
  • CORBA components.
  • COM+ components (ActiveX).
  • Java Classes.
  • ....

 DMI Clients

DMI clients used this DMI interface to make use of the objects.
Normally DMI client contains also a mapping into the client language.

  • ACDK C++.
  • Perl.
  • Lisp.
  • C++-COM clients.
  • VBScript/JavaScript.
  • Visual Basic.
  • Tcl.
  • Python.

 DMI Client and Server Implementation combinations

The client server interfaces can be connected. The advantage of this connectivity you can access DMI Servers (like a COM component) in with DMI client (like Perl) without additionally glue-code (Proxy, Stub, etc.) in a very natural way.

sub require_class($)
  my ($cls) = @_;
  my $cl = acdk::new(\"acdk/lang/ClassLoader\");

# acdkx/com/ComObject is not an ordinary object
# but a DMI Server implementation which overwrites the standard
# DMI Server methods
$word = acdk::invoke_static('acdkx/com/ComObject', 'New', 'Word.Application');

# access directly the COM-Object
$word->poke('Visible', 1);
$doc = $word->peek('Documents')->add();
$sel = $word->peek('ActiveWindow')->peek('Selection');

# 'TypeText' is not really a acdkx/com/ComObject but 
# a method of the Selection option of Word
$sel->TypeText(\"This is \");

$sel->peek('Font')->poke('Bold', 1);
$sel->peek('Font')->poke('Bold', 0);
$sel->TypeText(\" instrumenting Word through acdk_perl\");
acdk::invoke_static('acdk/lang/Thread', 'sleep', 3000);