2005/5/10

     
 

Subclassing using DMI

artefaktur

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


With DmiProxies foreign DMI Servers can implement ACDK Interfaces and extends existing classes.


Content of this chapter:

   Introduction
   The Problem
   The Solution: DMI Proxies
     marking classes as final
   Implement the interface in the language of your choice
     Create Interface implementations



 Introduction


As shown so long it is possible to call other objects methods through DMI, whereas DMI automatically hides the details of the invocation translation.

In object oriented software development not only functions are the common exported application interface, but also interfaces.

ACDK provides a mechanism, which makes it possible to implement an interface with any DMI Server implementations.

 The Problem

Given a native C++ interface:

class MyInterface
      ACDK_INTERFACEBASE
{
public:
   virtual void callIt() = 0;
};
If a script implements this interface it provides a function void callIt() which can be called through DMI.

If this method is called by the script itself the standard dispatching functionality of DMI calls the script implementation.

But in the case the script implementation want to provide this interface implementation a native C++ method (like a Iterator implementation to a Collection function) the native implementation doesn't know anything about the script implementation. It makes a native call to callIt().

 The Solution: DMI Proxies

The solution are native C++ DMI Proxy implementation of the native interface, which forwards the call to the script implementation.

You can use acdkmc -dmiproxy src/mymodule to generate DMI-Proxy implementation of the classes an interfaces in src/mymodule.

!

Due limitation of the acdkmc parser, you must have already compiled a mymodule shared library which contains the extended metainfo of this module.

The acdkmc loads this extended metainfo to retrieve all information about virtual methods of this class and their super classes and interfaces.
Rules for DMI Proxy:
  • DMI Proxy classes should have a default constructor.
    The default constructor can also be protected.
  • Proxies are only be generated for virtual methods
  • don't change visibility (public/private) in derived classes
  • In a class, which implements a abstract virtual method from a interface should not be tagged as foreign.

 marking classes as final

The pseudo keyword final can be used to mark classes which should not provide a DMI Proxy:

// for MyClass no DMI Proxy will be generated
final
class MyClass
: extends acdk::lang::Object
{
public:
  virtual void foo() { /*...*/ }
};

 Implement the interface in the language of your choice

A language, which makes use of the DMI proxies is  CfgScript.

Sample Implementation in CfgScript:

class CfgTask
extends acdk.lang.Object
implements Task
{
  Task() {}
  void callIt() { out.println("CfgTask called"); }
}

Sample Implementation in Java:


public class JavaTask
{
  /**
    Execute the command
    @param properties has the same interface like java.util.Properties
  */
  public int execute(String cmd, acdk.java.AcdkObject env)
  {
    if (cmd.equals("sayhello") == true)
    {
      System.out.println("Hello from Java");
      return 0;
    }
    return 1;
  }
}

Alternative implementation in Lisp

(defclass LispTask ()
 (
  (execute :initform 
            (lamda (cmd env)
              (if (cmd 'equals "sayhello")
                (progn
                  (println "Hello from Lisp")
                  (return 0)
                )
                (return 1)
              )
             )
   )
 )
)

 Create Interface implementations

!

This is outdated and must be updated in further version of this document.

  /* old doesn't work further
  RTask javatask = (RTask)Task::getDmiProxy(new ::acdk::java::JavaObject("JavaTask"));
  RTask lisptask = (RTask)Task::getDmiProxy(new ::acdk::lisp::LispObject("LispTask"));
  javatask->execute("sayhello", System::getProperties());  
  lisptask->execute("sayhello", System::getProperties());  
  */