PathEngine home previous: Handling Attributesnext: Ownership and Lifetimes
Contents, Programmers Guide, Applying the SDK, Miscellaneous API Issues, Passing Arrays

Passing Arrays

Some API methods need to pass arrays as input or output parameters.

To keep SDK linkage straightforward, and to support DLL linkage, we avoid passing STL container classes through the API interface. Instead arrays are passed in to the API with buffer pointers and sizes, and out of the API through a special callback class.

Passing arrays as input parameters

An example of this is iPathEngine::newShape(), with the following method definition:

std::unique_ptr<iShape> newShape(const int32_t* coordinates_Buffer, uint32_t coordinates_BufferEntries);

So the array is passed with two arguments, a buffer pointer (with _Buffer suffix) and a number of entries (with _BufferEntries suffix).

Some general rules with regards to passing arrays in this way are then as follows:

In some cases arrays can also be passed in to user supplied callback methods (e.g. in Interface iOutputStream), and it's important to for this to be taken into account in the callback method implementation. When implementing a callback which accepts arrays the callback code should check the number of entries first, and if this is zero then the buffer pointer should not be used.

Receiving arrays from output parameters

This is less common than array input parameters, but can't be avoided in certain specific cases. There is a special code for methods that return arrays of pointers to interface objects (see below).

A concrete example where we need to pass array data out of the API is iMeshFederation::getGroundTilesOverlapped(), with the following method definition:

void getGroundTilesOverlapped(int32_t tileIndex, const iSourceTiling& tiling, iArrayReceiver<int32_t>& results) const;

The Interface iArrayReceiver class is an abstract interface, and a callback object deriving from this needs to be provided to receive the result data.

This is not something you will normally need to do explicitly, however. An example derived class based on std::vector is supplied by the API header, cVectorReceiver, and you can usually just use this convenience class as shown in the following code snippet:

cVectorReceiver<int32_t> tiles;
federation->getGroundTilesOverlapped(tileIndex, sourceTiling, tiles);
// the set of overlapping tiles can now be queried in tiles.vector
// or tiles.vector can be swapped or moved out

In most cases that should be all you need to know, but in some performance critical situations it may be desirable to avoid memory allocations, and custom iArrayReceiver derived classes can then be set up for this purpose.

cVectorReceiver is defined as follows:

template <class T> class cVectorReceiver : public iArrayReceiver<T>
{
public:
    std::vector<T> vector;
    void
    receive(const T& element)
    {
        vector.push_back(element);
    }
};

Sometimes the maximum result size for a method returning array data can be determined in advance, and this can be replaced by an array receiver that writes into a fixed size buffer. (See the API documentation for each method, for details.)

Or sometimes it may be suffient just to call reserve() on the vector in a cVectorReceiver.

Array receiver classes can be defined to write to custom vector implementations (where in use), to stack memory, and so on.

Receiving arrays of interface objects

Methods with out arguments that return arrays of pointers to interface objects are treated as a special case. In this case the pointers to interface objects are returned wrapped with std::unique_ptr, and written directly to a vector. (See iMesh::getAllAgentsOverlapped() for an example of what this looks like.)


Documentation for PathEngine release 6.04 - Copyright © 2002-2024 PathEnginenext: Ownership and Lifetimes