next up previous contents index
Next: C++ Specific Babel Command Up: C++ Binding Previous: Implementing SIDL Classes in   Contents   Index


Accessing SIDL Arrays From C++

Although it is feasible to expose the underlying C array API to create, destroy and access array elements and meta-data, the C++ bindings provide a sidl::array<T> template mechanism that is more in keeping with C++ idioms.

For SIDL built-in types, template specializations of sidl::array<T> are defined in sidl_ucxx.hxx. For SIDL interface and classes, the array template is again specialized in the corresponding stub header. The reason for the extensive use of template specialization is an effort to hide the details that the array implementation shifts between the C++ type externally, and the C-based types stored in the IOR. (See basearray in sidl_ucxx.hxx for the traits classes and grungy implementation details.)

An example is given below.


int32_t len = 10; // array length=10
int32_t dim = 1;  // one dimensional
int32_t lower[1] = {0}; // zero offset
int32_t upper[1] = {len-1};
int32_t prime = nextPrime(0);

// create a SIDL array of primes.
sidl::array<int32_t> a = sidl::array<int32_t>::createRow(dim, lower, upper);
for( int i=0; i<len; ++i ) { 
   prime = nextPrime( prime );
   a.set(i, v);
}

Of course, the example above is only one way to create an array. The list of member functions for all C++ array classes is:


// constructors
array ( ior_array_t * src ); // internal
array ( const array & src ); // copy constructor

// destructor
~array() ;

// create row-size of 1 to 7 dimensions
static array<T>
createRow( int32_t dimen, const int32_t lower[], 
           const int32_t upper[]);

// create column-wise of 1 to 7 dimensions 
static array<T>
createCol( int32_t dimen, const int32_t lower[], 
           const int32_t upper[]);

// create 1-D array of specified length
static array<T> create1d( int32_t len );

// create 1-D array of specified length and init 
static array<T> create1d(int32_t len, ior_item_internal_t data) 

// create 2-D array of specified extents
static array<T> create2dCol( int32_t m, int32_t n);

// create 2-D array of specified extents
static array<T> create2dRow( int32_t m, int32_t n);

// get a slice of the array
array<T>
slice( int32_t dimen, const int32_t numElem[], 
       const int32_t *srcStart = 0,
       const int32_t *srcStride = 0,
       const int32_t *newStart = 0);

void borrow( item_ior_t * first_element, int32_t dimen,
        const int32_t lower[], const int32_t upper[], 
        const int32_t stride[]);

void ensure( int32_t dimen, array_ordering ordering );

void addRef();

void deleteRef();

// get/set
cxx_item_t get(int32_t i);
cxx_item_t get(int32_t i1, int32_t i2);
cxx_item_t get(int32_t i1, int32_t i2, int32_t i3);
cxx_item_t get(int32_t i1, int32_t i2, int32_t i3, 
		       int32_t i4);
cxx_item_t get(int32_t i1, int32_t i2, int32_t i3, 
		       int32_t i4, int32_t i5);
cxx_item_t get(int32_t i1, int32_t i2, int32_t i3, 
		       int32_t i4, int32_t i5, int32_t i6);
cxx_item_t get(int32_t i1, int32_t i2, int32_t i3, 
		       int32_t i4, int32_t i5, int32_t i6, int32_t i7);
cxx_item_t get(const int32_t *indices);

void set(int32_t i, cxx_item_t elem);
void set(int32_t i1, int32_t i2, cxx_item_t elem);
void set(int32_t i1, int32_t i2, int32_t i3,
	 cxx_item_t elem);
void set(int32_t i1, int32_t i2, int32_t i3, int32_t i4,
	 cxx_item_t elem);
void set(int32_t i1, int32_t i2, int32_t i3, int32_t i4,
	 int32_t i5, cxx_item_t elem);
void set(int32_t i1, int32_t i2, int32_t i3, int32_t i4,
	 int32_t i5, int32_t i6, cxx_item_t elem);
void set(int32_t i1, int32_t i2, int32_t i3, int32_t i4,
	 int32_t i5, int32_t i6, int32_t i7, cxx_item_t elem);
void set(const int32_t *indices, cxx_item_t elem);

// [] overloaded to be same as get(i)
cxx_item_t operator[](int32_t i) const ;

bool is1dPacked() const;

// returns STL forward iterator iff 1DPacked, else null
iterator begin();

// returns STL forward iterator iff 1DPacked, else null
const_iterator begin();

// returns STL forward iterator iff 1DPacked, else null
iterator end();

// returns STL forward iterator iff 1DPacked, else null
const_iterator end();

const int32_t* first() const;

int32_t* first();
                                                                                
void copy( const array< T >& src );


// other accessors
int32_t dimen() const;

int32_t lower( int32_t dim ) const;

int32_t upper( int32_t dim ) const;

int32_t stride( int32_t dim ) const;

bool _is_nil() const;

bool _not_nil() const;

// get a const pointer to the actual array ior 
const array_ior_t* _get_ior() const;

// get a non-const pointer to the actual array ior
array_ior_t* _get_ior();

void _set_ior( ior_array_t * s);
                                                                                
array& operator =(const array &rhs);
                                                                                
array& operator =(const basearray &rhs);

where cxx_array_t, cxx_item_t, ior_array_t, ior_item_t, ior_item_internal_t, iterator, const_iterator, pointer, and value_type are all public typedefs in the array class. The values of these typedefs are determined by traits classes. Traits classes are a fairly standard, albeit advanced, C++ templating idiom. Refer to any advanced C++ text for detailed explanation. As an example, we reproduce both the array_traits<> and array<> template specializations for int32_t here to show how what these typedefs are for that special case. Refer to sidl_ucxx.hxx for more built-in types and the UCxx stubs for the user-defined types.


 // template specialization for array_traits<int32_t>
  template<>
  struct array_traits<int32_t> {
    typedef array<int32_t>                            cxx_array_t;
    typedef int32_t                               cxx_item_t;
    typedef struct sidl_int__array                       ior_array_t;
    typedef int32_t                               ior_item_t;
    typedef const int32_t*      ior_item_internal_t;
    typedef cxx_item_t                               value_type;
    typedef value_type*                              pointer;
    typedef const value_type*                        const_pointer;
  };
 template<>
  class array< int32_t >
    : public basearray
  {
  public:
    typedef basearray                                  Base;
    typedef array_traits<int32_t>::cxx_array_t          cxx_array_t;
    typedef array_traits<int32_t>::cxx_item_t           cxx_item_t;
    typedef array_traits<int32_t>::ior_array_t          ior_array_t;
    typedef array_traits<int32_t>::ior_item_t           ior_item_t;
    typedef array_traits<int32_t>::ior_item_internal_t  ior_item_internal_t;
    typedef array_iter< array_traits<int32_t> >         iterator;
    typedef const_array_iter< array_traits<int32_t> >   const_iterator;
    typedef array_traits< int32_t > ::pointer         pointer;
    typedef array_traits< int32_t > ::value_type      value_type;
   
    // lots of methods to follow
  }

The C++ mapping for r-arrays is essentially identical to the mapping for C (see Section 6.4). The only difference is that the C++ client header provides an overloaded version of each method containing an r-array taking normal SIDL arrays instead of raw data. For example, the solve method from Section 5.4 produces the following code in the client-side header file.


    void solve (/*in*/    double* A,
                /*inout*/ double* x,
                /*in*/    double* b,
                /*in*/    int32_t m,
                /*in*/    int32_t n) throw ();

    void solve (/*in*/    ::sidl::array<double> A,
                /*inout*/ ::sidl::array<double>& x,
                /*in*/    ::sidl::array<double> b) throw();

Please note that multi-dimensional arrays, such as A in this case, are stored in column-major ordering. Babel provides macros to access r-array data correctly. In this example, you can use RarrayElem2(A, i, j, m) to access the element in row i and column j. There are similar macros for arrays of dimension 1 through 7 in sidlArray.h.

If you were implementing solve in C++, the Babel generated implementation file for it would look like this:


void num::Linsol_impl::solve (/*in*/    double* A,
                              /*inout*/ double* x,
                              /*in*/    double* b,
                              /*in*/    int32_t m,
                              /*in*/    int32_t n ) throw () 
{
  // DO-NOT-DELETE splicer.begin(num.Linsol.solve)
  // insert implementation here
  // DO-NOT-DELETE splicer.end(num.Linsol.solve)
}

To access memory by stride one make the row index your inner loop and the column index your outer loop.


next up previous contents index
Next: C++ Specific Babel Command Up: C++ Binding Previous: Implementing SIDL Classes in   Contents   Index


babel-0.99.0
users_guide Last Modified 2006-06-27

http://www.llnl.gov/CASC/components
components@llnl.gov