Archived

This forum has been archived. Please start a new discussion on GitHub.

a question about Classes as Unions

Hi,

I define some classes as below:

/////////////////////////////////////////////////////
enum VARTYPE { VTNULL, VTBOOL, VTBYTE, VTSHORT, VTINT, VTLONG, VTFLOAT, VTDOUBLE, VTSTRING, VTBLOB, VTSTRINGBLOB };

class Variant{
string toString();
int fromString(string s);
VARTYPE getType();
};

class VariantBoolean extends Variant { bool value; };

class VariantByte extends Variant { byte value; };

class ComplexObj{
int i;
Variant value;
};

interface MyOp{
int submit(ComplexObj obj);
};
//////////////////////////////////////////////////////////////////

In the client side, member "value" of ComplexObj object is instantiated as VariantBooleanI object.
After client invoke submit() of MyOp, the server throws an exception as below:

//////////////////////////////////////////////////////////////////
infoprocmgt: warning: dispatch exception: g:\def.
cpp:1521: Ice::NoObjectFactoryException:
protocol error: no suitable object factory found for `Variant'
identity: MyOp.submit
facet:
operation: submit

//////////////////////////////////////////////////////

do Ice support the semantics?

Thanks in advance.

FengXB

Comments

  • matthew
    matthew NL, Canada
    Yes. But you have to install an object factory for the types you expect to use in your application. See the Ice manual for more information.
  • Thanks a lot. It works.
  • Hello,

    I am a newbie and looking at ice-e now as 1st time.

    I am basically in the same need: defining a variant type to serialize/deserialize
    over the wire.
    In SOAP I use anytype for that. With slice (ICE-E),
    how I define a variant that can hold a sequence of bytes?

    class VariantBINARY extends Variant { sequence<byte> value; };
    would pops a syntax error.

    Thanks in advance,
    Marco Monguzzi
  • matthew
    matthew NL, Canada
    You cannot directly use a sequence like that. You must first typedef it and use the resulting type. sequence<byte> is pre-defined in slice/Ice/BuiltinSequences.ice. So you can do something like:

    #include <Ice/BuiltinSequences.ice>

    class VariantBINARY extends Variant { Ice::ByteSeq value; };

    Also note that with Ice-E you cannot send a class by-value over the wire.
  • Hi Matthew,

    thanks for your reply.
    matthew wrote: »
    Also note that with Ice-E you cannot send a class by-value over the wire.

    what options I have in ICE-E to transfer instances of TRV defined below:

    enum VTYPE
    {
    VTEMPTY,
    VTBIT,
    VTBYTE,
    VTSHORT,
    VTINT,
    VTUBYTE,
    VTUSHORT,
    VTUINT,
    VTFLOAT,
    VTDOUBLE,
    VTSTRING,
    VTBINARY,
    VTTIME
    };

    struct Timestamp
    {
    long utc;
    short msec;
    };

    //FIXME: need support for UBYTE, USHORT, UINT
    class Variant { VTYPE type; };
    class VariantBIT extends Variant { bool value; };
    class VariantBYTE extends Variant { byte value; };
    class VariantSHORT extends Variant { short value; };
    class VariantINT extends Variant { int value; };
    class VariantFLOAT extends Variant { float value; };
    class VariantDOUBLE extends Variant { double value; };
    class VariantSTRING extends Variant { string value; };
    class VariantTIME extends Variant { Timestamp value; };
    //FIXME: binary as seq of bytes?
    class VariantBINARY extends Variant { Ice::ByteSeq value; };

    struct TRV
    {
    int ec;
    Timestamp ts;
    byte qual;
    Variant value;
    };

    I see I can compile with slice2cpp for ICE but not for ICE-E. As you mentioned
    slice for ICE-E warns that 'struct data member 'value' cannot be a value object'. Should I consider the full blown ICE?


    Thanks
    Marco
  • One way to emulate a union with Ice-E is to do the following:
    enum Discriminator { A, B, C };
    sequence<TypeA> ASeq;
    sequence<TypeB> BSeq;
    sequence<TypeB> CSeq;
    
    struct Variant {
        Discriminator activeType;
        ASeq a;
        BSeq b;
        CSeq c;
    };
    

    Basically, you have a sequence for each possible type and the struct contains one member of each sequence type, plus the discriminator that tells you which type is conceptually active. The sequences are all empty, except for the one indicated by the discriminator, which contains only a single element.

    This is not quite as convenient as using derived classes but, in practice, it's workable, and it is quite efficient: the empty sequences consume only a single byte each on the wire.

    Cheers,

    Michi.
  • bernard
    bernard Jupiter, FL
    Hi Marco,
    mmongu wrote: »
    Should I consider the full blown ICE?

    This very much depends on your target platform. If you have just a few MBs of flash and RAM, then you should probably use Ice-E. Otherwise, you can use Ice.

    In particular, if your target is a regular Intel/AMD Linux/Windows system, there is no compelling reason to use Ice-E instead of Ice.

    Best regards,
    Bernard
  • Hi Michi,
    thanks for the hint. I will try that way.
    Marco
  • bernard wrote: »
    Hi Marco,



    This very much depends on your target platform. If you have just a few MBs of flash and RAM, then you should probably use Ice-E. Otherwise, you can use Ice.

    In particular, if your target is a regular Intel/AMD Linux/Windows system, there is no compelling reason to use Ice-E instead of Ice.

    Best regards,
    Bernard

    Hi Bernard,

    thanks for your reply. My test case would target custom embedded platforms as servers (MIPS vr4131@200MHz/wce4.2/64MB RAM/128MB flash) and commercial PDA/mobiles as clients (WCE5 and symbian). Even thought the work behind the full ICE is amazing, I am afraid it wouldn't fit my needs. The idea is comparing against rtcorba, embedded soap and custom protocols.

    Marco