Index: src/client/c/hu/varadiistvan/xplra/xplra.cc
===================================================================
--- src/client/c/hu/varadiistvan/xplra/xplra.cc	(revision 27)
+++ src/client/c/hu/varadiistvan/xplra/xplra.cc	(revision 28)
@@ -32,4 +32,6 @@
 
 #include "XPlane.h"
+#include "MultiGetter.h"
+#include "MultiSetter.h"
 #include "Exception.h"
 
@@ -43,4 +45,7 @@
 
 using hu::varadiistvan::xplra::XPlane;
+using hu::varadiistvan::xplra::MultiBuffer;
+using hu::varadiistvan::xplra::MultiGetter;
+using hu::varadiistvan::xplra::MultiSetter;
 using hu::varadiistvan::xplra::Exception;
 using hu::varadiistvan::xplra::IOException;
@@ -53,4 +58,5 @@
 using std::string;
 using std::vector;
+using std::set;
 using std::auto_ptr;
 
@@ -59,4 +65,170 @@
 namespace {
 
+//------------------------------------------------------------------------------
+
+/**
+ * Template for handling slots.
+ */
+template <class Value>
+struct Slot
+{
+private:
+    /**
+     * The slots.
+     */
+    static std::vector< Slot<Value> > slots;
+
+    /**
+     * The index of the first free slot.
+     */
+    static int firstFree;
+
+public:
+    /**
+     * Add a new value.
+     *
+     * @return the ID of the new value
+     */
+    static int addValue(Value value) throw();
+
+    /**
+     * Get the value with the given ID.
+     */
+    static Value getValue(int valueID) throw();
+
+    /**
+     * Clear the value with the given ID.
+     */
+    static void clearValue(int valueID) throw();
+
+private:
+    /**
+     * Indicate if the slot contains a valid value or not.
+     */
+    bool valid;
+
+    union {
+        // The value, if the slot contains a value
+        Value value;
+
+        // The index of the next free slot
+        int nextFreeIndex;
+    };
+
+    /**
+     * Construct a slot with the given value
+     */
+    Slot(Value value) throw();
+
+    /**
+     * Set the value and return the former next free index. It
+     * should be called for a slot with no value.
+     */
+    int setValue(Value value) throw();
+
+    /**
+     * Get the value if this slot contains a value. Otherwise 0 is
+     * returned (converted to value).
+     */
+    Value getValue() const throw();
+
+    /**
+     * Clear the value and set the given next free index.
+     */
+    void clear(int nextFreeIndex) throw();
+};
+
+//------------------------------------------------------------------------------
+
+template <class Value> vector< Slot<Value> > Slot<Value>::slots;
+
+//------------------------------------------------------------------------------
+
+template <class Value> int Slot<Value>::firstFree = -1;
+
+//------------------------------------------------------------------------------
+
+template <class Value>
+inline Slot<Value>::Slot(Value value) throw() :
+    valid(true)
+{
+    this->value = value;
+}
+
+//------------------------------------------------------------------------------
+
+template <class Value>
+inline int Slot<Value>::setValue(Value value) throw()
+{
+    assert(!valid);
+    int nextFreeIndex = this->nextFreeIndex;
+    this->value = value;
+    valid = true;
+    return nextFreeIndex;
+}
+
+//------------------------------------------------------------------------------
+
+template <class Value>
+inline Value Slot<Value>::getValue() const throw()
+{
+    return valid ? value : static_cast<Value>(0);
+}
+
+//------------------------------------------------------------------------------
+
+template <class Value>
+inline void Slot<Value>::clear(int nextFreeIndex) throw()
+{
+    assert(valid);
+    valid = false;
+    this->nextFreeIndex = nextFreeIndex;
+}
+
+//------------------------------------------------------------------------------
+
+template <class Value>
+int Slot<Value>::addValue(Value value) throw()
+{
+    int id = firstFree;
+    if (id<0) {
+        id = slots.size();
+        slots.push_back(Slot<Value>(value));
+    } else {
+        Slot& slot = slots[id];
+        firstFree = slot.setValue(value);
+    }
+
+    return id;
+}
+
+//------------------------------------------------------------------------------
+
+template <class Value>
+Value Slot<Value>::getValue(int valueID) throw()
+{
+    size_t index = static_cast<size_t>(valueID);
+    return (index<slots.size()) ?
+        slots[index].getValue() : static_cast<Value>(0);
+}
+
+//------------------------------------------------------------------------------
+
+template <class Value>
+void Slot<Value>::clearValue(int valueID) throw()
+{
+    size_t index = static_cast<size_t>(valueID);
+    if (index<slots.size()) {
+        slots[index].clear(firstFree);
+        firstFree = index;
+    }
+}
+
+//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
+
+typedef Slot<MultiBuffer*> MultiBufferSlot;
+
+//------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
 
@@ -68,4 +240,9 @@
 private:
     /**
+     * Type for the set of multi-dataref buffers belonging to this connection.
+     */
+    typedef std::set<int> multiBufferIDs_t;
+
+    /**
      * The last error code.
      */
@@ -82,4 +259,9 @@
     std::string lastErrorString;
 
+    /**
+     * The set of multi-dataref buffers belonging to this connection.
+     */
+    multiBufferIDs_t multiBufferIDs;
+
 public:
     /**
@@ -89,4 +271,9 @@
 
     /**
+     * Destroy the connection.
+     */
+    ~Connection() throw();
+
+    /**
      * Handle the currently pending exception.
      */
@@ -107,4 +294,28 @@
      */
     void clearLastError() throw();
+
+    /**
+     * Create a multi-dataref getter object and register it in a slot.
+     *
+     * @return the ID of the new getter.
+     */
+    int createMultiGetter() throw();
+
+    /**
+     * Create a multi-dataref setter object and register it in a slot.
+     *
+     * @return the ID of the new setter.
+     */
+    int createMultiSetter() throw();
+
+    /**
+     * Destroy the multi-dataref buffer with the given ID.
+     *
+     * @param bufferID the ID of the buffer. It should be a valid ID,
+     * that belongs to this connection.
+     *
+     * @return whether the buffer was found and could be destroyed.
+     */
+    bool destroyMultiBuffer(int bufferID) throw(Exception);
 };
 
@@ -115,4 +326,15 @@
     lastErrorSubCode(0)
 {
+}
+
+//------------------------------------------------------------------------------
+
+Connection::~Connection() throw()
+{
+    for(multiBufferIDs_t::iterator i = multiBufferIDs.begin();
+        i!=multiBufferIDs.end(); ++i)
+    {
+        MultiBufferSlot::clearValue(*i);
+    }
 }
 
@@ -180,161 +402,32 @@
 
 //------------------------------------------------------------------------------
-//------------------------------------------------------------------------------
-
-/**
- * Template for handling slots.
- */
-template <class Value>
-struct Slot
-{
-private:
-    /**
-     * The slots.
-     */
-    static std::vector< Slot<Value> > slots;
-
-    /**
-     * The index of the first free slot.
-     */
-    static int firstFree;
-
-public:
-    /**
-     * Add a new value.
-     *
-     * @return the ID of the new value
-     */
-    static int addValue(Value value) throw();
-
-    /**
-     * Get the value with the given ID.
-     */
-    static Value getValue(int valueID) throw();
-
-    /**
-     * Clear the value with the given ID.
-     */
-    static void clearValue(int valueID) throw();
-
-private:
-    /**
-     * Indicate if the slot contains a valid value or not.
-     */
-    bool valid;
-
-    union {
-        // The value, if the slot contains a value
-        Value value;
-
-        // The index of the next free slot
-        int nextFreeIndex;
-    };
-
-    /**
-     * Construct a slot with the given value
-     */
-    Slot(Value value) throw();
-
-    /**
-     * Set the value and return the former next free index. It
-     * should be called for a slot with no value.
-     */
-    int setValue(Value value) throw();
-
-    /**
-     * Get the value if this slot contains a value. Otherwise 0 is
-     * returned (converted to value).
-     */
-    Value getValue() const throw();
-
-    /**
-     * Clear the value and set the given next free index.
-     */
-    void clear(int nextFreeIndex) throw();
-};
-
-//------------------------------------------------------------------------------
-
-template <class Value> vector< Slot<Value> > Slot<Value>::slots;
-
-//------------------------------------------------------------------------------
-
-template <class Value> int Slot<Value>::firstFree = -1;
-
-//------------------------------------------------------------------------------
-
-template <class Value>
-inline Slot<Value>::Slot(Value value) throw() :
-    valid(true)
-{
-    this->value = value;
-}
-
-//------------------------------------------------------------------------------
-
-template <class Value>
-inline int Slot<Value>::setValue(Value value) throw()
-{
-    assert(!valid);
-    int nextFreeIndex = this->nextFreeIndex;
-    this->value = value;
-    valid = true;
-    return nextFreeIndex;
-}
-
-//------------------------------------------------------------------------------
-
-template <class Value>
-inline Value Slot<Value>::getValue() const throw()
-{
-    return valid ? value : static_cast<Value>(0);
-}
-
-//------------------------------------------------------------------------------
-
-template <class Value>
-inline void Slot<Value>::clear(int nextFreeIndex) throw()
-{
-    assert(valid);
-    valid = false;
-    this->nextFreeIndex = nextFreeIndex;
-}
-
-//------------------------------------------------------------------------------
-
-template <class Value>
-int Slot<Value>::addValue(Value value) throw()
-{
-    int id = firstFree;
-    if (id<0) {
-        id = slots.size();
-        slots.push_back(Slot<Value>(value));
+
+inline int Connection::createMultiGetter() throw()
+{
+    MultiGetter& getter = XPlane::createMultiGetter();
+    return MultiBufferSlot::addValue(&getter);
+}
+
+//------------------------------------------------------------------------------
+
+inline int Connection::createMultiSetter() throw()
+{
+    MultiSetter& setter = XPlane::createMultiSetter();
+    return MultiBufferSlot::addValue(&setter);
+}
+
+//------------------------------------------------------------------------------
+
+bool Connection::destroyMultiBuffer(int bufferID) throw(Exception)
+{
+    MultiBuffer* buffer = MultiBufferSlot::getValue(bufferID);
+    if (buffer==0) return false;
+
+    if (XPlane::destroyMultiBuffer(*buffer)) {
+        multiBufferIDs.erase(bufferID);
+        MultiBufferSlot::clearValue(bufferID);
+        return true;
     } else {
-        Slot& slot = slots[id];
-        firstFree = slot.setValue(value);
-    }
-
-    return id;
-}
-
-//------------------------------------------------------------------------------
-
-template <class Value>
-Value Slot<Value>::getValue(int valueID) throw()
-{
-    size_t index = static_cast<size_t>(valueID);
-    return (index<slots.size()) ?
-        slots[index].getValue() : static_cast<Value>(0);
-}
-
-//------------------------------------------------------------------------------
-
-template <class Value>
-void Slot<Value>::clearValue(int valueID) throw()
-{
-    size_t index = static_cast<size_t>(valueID);
-    if (index<slots.size()) {
-        slots[index].clear(firstFree);
-        firstFree = index;
+        return false;
     }
 }
@@ -641,4 +734,37 @@
 }
 
+//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
+
+extern "C" int xplra_create_multi_getter(int connectionID)
+{
+    Connection* connection = ConnectionSlot::getValue(connectionID);
+    return (connection==0) ? -1 : connection->createMultiGetter();
+}
+
+//------------------------------------------------------------------------------
+
+extern "C" int xplra_create_multi_setter(int connectionID)
+{
+    Connection* connection = ConnectionSlot::getValue(connectionID);
+    return (connection==0) ? -1 : connection->createMultiSetter();
+}
+
+//------------------------------------------------------------------------------
+
+extern "C" int xplra_destroy_multi_buffer(int connectionID, int bufferID)
+{
+    Connection* connection = ConnectionSlot::getValue(connectionID);
+    if (connection==0) return -1;
+
+    try {
+        return connection->destroyMultiBuffer(bufferID) ? 0 : -1;
+    } catch(...) {
+        connection->handleException();
+        return -1;
+    }
+}
+
+//------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
 
Index: src/client/c/hu/varadiistvan/xplra/xplra.h
===================================================================
--- src/client/c/hu/varadiistvan/xplra/xplra.h	(revision 27)
+++ src/client/c/hu/varadiistvan/xplra/xplra.h	(revision 28)
@@ -320,5 +320,31 @@
 /*----------------------------------------------------------------------------*/
 
-
+/**
+ * Create a multi-dataref getter for the given connection.
+ *
+ * @return the ID of the new getter, or -1 on error
+ */
+int xplra_create_multi_getter(int connectionID);
+
+/*----------------------------------------------------------------------------*/
+
+/**
+ * Create a multi-dataref setter for the given connection.
+ *
+ * @return the ID of the new setter, or -1 on error
+ */
+int xplra_create_multi_setter(int connectionID);
+
+/*----------------------------------------------------------------------------*/
+
+/**
+ * Destruy a multi-dataref buffer for the given connection.
+ *
+ * @param connectionID the ID of the connection for which the buffer
+ * has been created.
+ *
+ * @return 0 on success, -1 on error.
+ */
+int xplra_destroy_multi_buffer(int connectionID, int bufferID);
 
 /*----------------------------------------------------------------------------*/
