Build simple value objects

Most DataBlade® developers want to create true value objects for new types. The simplest way to do so is to derive a C++ class directly from the ITDatum interface class. You must then add to the new class:
  • Implementation for all the ITDatum methods, all of which are pure virtual.
  • Any data members needed to hold the data of the object
  • A few data members required to support the ITDatum methods; in particular, an ITTypeInfo object.
  • A class constructor and destructor.
If your value object code is to be directly linked with your application, you must add:
  • A static class factory function that calls the class constructor.

    The class factory function must accept an instance of an ITMVDesc structure.

  • A global ITFactoryList object that registers the class factory function under a server type name.
If you want to use dynamic loading feature, you must provide:
  • A C-linkage factory function that calls the class constructor.

    The function must accept an instance of an ITMVDesc structure.

  • An entry in the map file for this class.

    For details, see Dynamic loading.

The simpval.cpp example illustrates the use of the ITMVDesc descriptor and ITDatum interface. The simpval.cpp example creates a true value object for the bitarray data type.

The following simpval.cpp code excerpts show how to create a true value object:
  1. Define the data structures for holding the bit array objects.
    typedef mi_integer bitarray_t;
  2. Define the array of integers class from ITDatum, implementing methods for the ITDatum abstract methods.
    class Bitarray : public ITDatum
    {
    public:
    
        // Overrides of ITEssential methods
        virtual ITOpErrorCode IT_STDCALL QueryInterface
                                             (const ITInterfaceID &ifiid,
                                                        void **resultif);
        virtual unsigned long IT_STDCALL AddRef();
        virtual unsigned long IT_STDCALL Release();
    
        // Overrides of ITValue methods
        virtual const ITString & IT_STDCALL Printable();
        virtual const ITTypeInfo & IT_STDCALL TypeOf();
        virtual ITBool IT_STDCALL IsNull();
        virtual ITBool IT_STDCALL SameType(ITValue *);
        virtual ITBool IT_STDCALL CompatibleType(ITValue *);
        virtual ITBool IT_STDCALL Equal(ITValue *);
        virtual ITBool IT_STDCALL LessThan(ITValue *);
        virtual ITBool IT_STDCALL IsUpdated();
        virtual ITBool IT_STDCALL FromPrintable(const ITString &);
        virtual ITBool IT_STDCALL SetNull();
    
        // Overrides of ITDatum methods
        virtual MI_DATUM IT_STDCALL Data();
        virtual long IT_STDCALL DataLength();
        virtual ITBool IT_STDCALL SetData(MI_DATUM, long, ITPreserveData *);
        virtual const ITConnection & IT_STDCALL Connection();
    
        // Class constructor, destructor
        Bitarray(ITMVDesc *);
        ~Bitarray();
    
        // Factory Constructor -- this is the entry point for objects to
        // be created. It uses the class constructor to build an object
        // and returns in to the caller. It is called automatically by the
        // Interface when an object of the "bitarray" type is returned by
        // the server to the interface
        static ITValue *MakeValue(ITMVDesc *);
    
        // Data members to implement ITEssential functionality
        long refcount;
    
        // Data members to implement ITValue functionality
        ITTypeInfo typeinfo;
        ITBool isnull, isupdated;
        ITString printable_value;
    
        // Data members to implement bitarray storage
        bitarray_t value;
    
        ITConnection conn;
    };
  3. Construct the object, initializing its reference count and data and type information.
    Bitarray::Bitarray(ITMVDesc *mv)
        : refcount(1),
          typeinfo(*mv->vf_origtypeinfo),
          isupdated(FALSE),
          conn(*mv->vf_connection)
    {
        // NULL?
        isnull = mv->vf_libmivaluetype == MI_NULL_VALUE;
        if(!isnull)
            value = *(bitarray_t *)mv->vf_data;
    }
  4. Define the factory entry point for the object.
    ITFactoryList BitarrayFactory("bitarray",
                                  Bitarray::MakeValue);

    When this object file is linked into the application, the linker forces the construction of the BitarrayFactory variable to take place before the application begins to execute. The ITFactoryList constructor puts the mapping from server type to Bitarray::MakeValue into the global type mapping list.

  5. Implement the factory entry point, which must be a static member function instead of a method, because at the time the factory entry point is called there is no object on which to call a method.
    ITValue *
    Bitarray::MakeValue(ITMVDesc *mv)
    {
        return new Bitarray(mv);
    }

    This function builds a new Bitarray object and returns it. Because the object derives from the ITDatum interface, it is valid to return the object itself instead of calling ITEssential::QueryInterface on the object to extract the correct interface.

  6. Define the ITEssential::QueryInterface function and the reference count methods.
    ITOpErrorCode
    Bitarray::QueryInterface(const ITInterfaceID &iid,
                                    void **ifptr)
    {
        int result = IT_QUERYINTERFACE_SUCCESS;
    
        switch (ITIIDtoSID(iid))
        {
            case ITEssentialSID:
            case ITValueSID:
            case ITDatumSID:
                *ifptr = this;
                break;
    
            default:
                result = IT_QUERYINTERFACE_FAILED;
                *ifptr = NULL;
                break;
        }
        if (result == IT_QUERYINTERFACE_SUCCESS)
            AddRef();
    
        return result;
    }
  7. Implement the ITDatum methods appropriate for the object.
    const ITString &
    Bitarray::Printable()
    {
        if(IsNull())
            return printable_value = "null";
    
        char buf[32];
        ostrstream cstream(buf, sizeof buf);
        cstream << value << ends;
        return printable_value = cstream.str();
    }