For SIDL built-in types, template specializations of sidl::array<T> are defined in sidl_cxx.hh. 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 detail that the array implementation is really templated on three terms: the type of the C struct that represents the array internally, the internal representation of each item in the array, and the C++ representation of each item in the array. (See array_mixin in sidl_cxx.hh for 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 ( array_ior_t * src ); // internal array () ; // empty // destructor ~array() ; // creation static array<x> createRow( int32_t dimen, const int32_t lower[], const int32_t upper[]); static array<x> createCol( int32_t dimen, const int32_t lower[], const int32_t upper[]); static array<x> create1d( int32_t len); static array<x> create2dCol( int32_t m, int32_t n); static array<x> create2dRow( int32_t m, int32_t n); array<x> 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 addRef(); void deleteRef(); // get/set item_cxx_wrapper_t get(int32_t i); item_cxx_wrapper_t get(int32_t i1, int32_t i2); item_cxx_wrapper_t get(int32_t i1, int32_t i2, int32_t i3); item_cxx_wrapper_t get(int32_t i1, int32_t i2, int32_t i3, int32_t i4); item_cxx_wrapper_t get(const int32_t *indices); void set(int32_t i, item_cxx_wrapper_t elem); void set(int32_t i1, int32_t i2, item_cxx_wrapper_t elem); void set(int32_t i1, int32_t i2, int32_t i3, item_cxx_wrapper_t elem); void set(int32_t i1, int32_t i2, int32_t i3, int32_t i4, item_cxx_wrapper_t elem); void set(const int32_t *indices, item_cxx_wrapper_t elem); // 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 { return d_array; } // get a non-const pointer to the actual array ior array_ior_t* _get_ior() { return d_array;}
where
Please note that all SIDL array constructors are static methods returning a newly allocated array. Normally, you assign the return value to a variable.
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.