# Introduction to MCOP for CORBA users

When you were using CORBA before, you will see that MCOP is much the same thing.

So the basic idea of CORBA remains: you implement objects (components). By using the MCOP features, your objects are not only available as normal classes from the same process (via standard C++ techniques) - they also are available to remote servers.

Transparently. For this to work, the first thing you need to do is to specify the interface of your objects in an IDL file - just like CORBA IDL. There are only a few differences.

## Differences in the IDL

### Things that are missing against CORBA IDL

- there are no "in" and "out" parameters on method invocations

  parameters are always incoming - the returncode is always outgoing, which means that the interface

      // CORBA idl

      interface Account {
        void deposit( in long amount );
        void withdraw( in long amount );
        long balance();
      };

  is written as

      // MCOP idl

      interface Account {
        void deposit( long amount );
        void withdraw( long amount );
        long balance();
      };

  in MCOP.
- no exception support

  MCOP doesn't have exceptions - use something else for error handling.

- no union types, no typedefs

  I don't know if that is a real weakness - something one would despereately need to survive.

- currently unsupported (expect this to be fixed some time)
  - no support for passing interfaces/object references

### Things that are different against CORBA IDL

- you declare sequences as sequence<[type]> in MCOP. No need to typedef.

  Example: instead of

      // CORBA idl

      struct Line {
          long x1,y1,x2,y2;
      };

      typedef sequence<Line> LineSeq;

      interface Plotter {
          void draw(in LineSeq lines);
      };

  you write

      // MCOP idl

      struct Line {
          long x1,y1,x2,y2;
      };

      interface Plotter {
          void draw(sequence<Line> lines);
      };

### Things that are new in MCOP IDL

You can declare streams, which will then be evaluated by the aRts framework.

Streams are declared similar to attributes, for instance:

    // MCOP idl

    interface Synth_ADD : SynthModule {
        in audio stream signal1,signal2;
        out audio stream outvalue;
    };

This does say that your object will accept two incoming synchronous audio streams, that are called signal1 and signal2.

By saying synchronous I mean: these are streams that deliver synchoneously x samples per second (or other time), so that the scheduler will guarantee to always provide you a balanced amount of input data (e.g. 200 samples of signal1 are there and 200 samples signal2 are there).

You guarantee that if your object is called with those 200 samples signal1 + signal2, it is able to produce exactly 200 samples outvalue - that is what synchronous operation means.

## The MCOP C++ language binding

This differs from CORBA mostly. However here it is:

### strings...

are using the C++ STL "string" class. When stored in sequences, they are stored "plain", that means they are considered to be a primitive type. Thus, they need copying.

### longs...

are plain long's (expected to be 32 bit)

### sequences...

are using the C++ STL "vector" class.

### structures...

are all derived from the MCOP class "Type", and generated by the MCOP idl compiler. When stored in sequences, they are not stored "plain", but as pointers, as otherwise, too much copying would occur.

### Implementing MCOP objects

After having them passed through the IDL compiler, you need to derive from the _skel class. For instance, consider you have defined your interface like that

    // MCOP idl: hello.idl

    interface Hello {
        void hello(string s);
        string concat(string s1, string s2);
        long sum2(long a, long b);
    };

You pass that through the IDL compiler by calling "mcopidl hello.idl", which will in turn generate hello.cc and hello.h.

To implement it, you need to define a C++-class that inherits the skeleton:

    // C++ header file - include hello.h somewhere

    class Hello_impl : virtual public Hello_skel {
    public:
        void hello(const string& s);
        string concat(const string& s1, const string& s2);
        long sum2(long a, long b);
    };

Finally, you need to implement the methods as normal C++

    // C++ implementation file

    // as you see string's are passed as const string references
    void Hello_impl::hello(const string& s)
    {
        printf("Hello '%s'!\n",s.c_str());
    }

    // when they are a returncode they are passed as "normal" strings
    string Hello_impl::concat(const string& s1, const string& s2)
    {
        return s1+s2;
    }

    long Hello_impl::sum2(long a, long b)
    {
        return a+b;
    }

    Once you did that, you have an object which can communicate using MCOP.
    Just create one (using the normal C++ facilities to create an object)

        Hello_impl server;

    And as soon as you give somebody the reference

        string reference = server._toString();
        printf("%s\n",reference.c_str());

    and go to the MCOP idle loop

    Dispatcher::the()->run();

    People can access the thing using

    // this code can run anywhere - not necessarily in the same process
    // (it may also run on a different computer/architecture)

        Hello *h = Hello::_fromString([the object reference printed above]);

    and invoke methods:

        if(h)
            h->hello("test");
        else
            printf("Access failed?\n");

    back to index