MCOP for CORBA-brugere

Hvis du har brugt CORBA tidligere, vil du kunne mærke at MCOP er meget lig. I virkeligheden så brugte aRts CORBA inden version 0.4.

Den grundlæggende idé med CORBA er den samme: man implementerer objekter (komponenter). Ved at bruge funktionerne i MCOP er objekter ikke kun tilgængelige som normale klasser fra samme proces (via standard C++ teknikker), men de er også transparent tilgængelige for en fjernserver. For at dette skal virke, er det første du skal gøre at specificere grænsefladen for dine objekter i en IDL-fil, præcis som for CORBA-IDL. Der er kun et fåtal af forskelle.

CORBA-funktioner som mangles i MCOP

I MCOP er der ingen “in” og “out” parametre for metodekald. Parametre er altid indgående, og returværdien er altid udgående, hvilket betyder at grænsefladen:

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

skrives som

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

i MCOP.

Der er ingen støtte for undtagelser. MCOP har ikke undtagelser, den bruger noget andet til fejlhåndtering.

Der er ingen union-typer og ingen typedefinitioner. Jeg ved ikke om det er en virkelig svaghed, noget man desperat behøver for at overleve.

Der er ingen understøttelse for at sende grænseflader eller objektreferencer

CORBA-funktioner som er anderledes i MCOP

Du deklarerer sekvenser som “sequencetyp” i MCOP. Der er intet behov for en typedefinition. For eksempel, i stedet for:

// CORBA idl
struct Line {
    long x1,y1,x2,y2;
};
typedef sequence<Line> LineSeq;
interface Plotter {
    void draw(in LineSeq lines);
};

ville du skrive

// MCOP idl
struct Line {
    long x1,y1,x2,y2;
};
interface Plotter {
    void draw(sequence<Line> lines);
};

MCOP-funktioner som ikke findes i CORBA

Du kan deklarere strømme, som senere behandles af aRts' skelet. Strømme deklareres på en måde som ligner egenskaber. For eksempel:

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

Dette betyder at dit objekt vil acceptere to indkommende synkrone lydstrømme som kaldes signal1 og signal2. Synkron betyder at de er strømme som leverer x samplinger pr sekund (eller anden tid), så skemalæggeren altid garanterer at du får en balanceret mængde inddata (f.eks. 200 samplinger af signal1 er der og 200 samplinger af signal2 er der). Du garanterer at hvis dit objekt kaldes med disse 200 samplinger af signal1 + signal2, så kan det producere præcis 200 samplinger uddata.

MCOP-bindingen til C++ sproget

Dette adskiller sig fra CORBA i hovedsagen hvad angår:

  • Strenge bruger C++ STL-klassen string. Når de opbevares i sekvenser, opbevares de “enkelt”, hvilket betyder at de anses for at være en primitiv type. Derfor behøver de at blive kopieret.

  • long er enkle long (forventes at være 32 bit).

  • Sekvenser bruger C++ STL-klassen vector.

  • Strukturer afledes alle fra MCOP klassen Type, og genereres af MCOP IDL-oversætteren. Når de opbevares i sekvenser, opbevares de ikke “enkelt”, men som pegere, eftersom der ellers ville opstå for meget kopiering.

Implementering af MCOP-objekter

Efter at have sendt dem gennem IDL-oversætteren, skal du aflede fra klassen _skel. Antag for eksempel at du har defineret grænsefladen sådan her:

// MCOP idl: hello.idl
interface Hello {
    void hello(string s);
    string concat(string s1, string s2);
    long sum2(long a, long b);
};

Du sender det gennem IDL-oversætteren ved at kalde mcopidl hello.idl, som derefter laver hello.cc og hello.h. For at implementere dette, behøver du en C++ klasse som arver skelettet:

// C++ deklarationsfil - indsæt hello.h et sted
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);
};

Til sidst skal du implementere metoderne som almindelig C++.

// C++ implementeringsfil

// som du ser sendes strenge som konstante strengreferencer
void Hello_impl::hello(const string& s)
{
    printf("Hello '%s'!\n",s.c_str());
}

// når de er en returværdi sendes de som "normale" strenge
string Hello_impl::concat(const string& s1, const string& s2)
{
    return s1+s2;
}

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

Når du har gjort dette, har du et objekt som kan kommunikere med MCOP. Opret kun et (med de normale C++ faciliteter til at oprette et objekt):

Hello_impl server;

Og så snart du giver nogen referencen

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

og gå til MCOP:s venteløkke

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

har alle adgang til objektet med

// denne kode kan køre hvorsomhelst - ikke nødvendigtvis i samme proces
// (den kan også køre på en anden maskine/arkitektur)

    Hello *h = Hello::_fromString([objektreferencen som blev udskrevet ovenifor]);

og kalde-metoder:

if(h)
        h->hello("test");
    else
        printf("Adgang mislykkedes?\n");