Server-Side C++ Mapping for Interfaces
Skeleton Classes
On the server side, interfaces map to skeleton classes. A skeleton is a class that has a pure virtual member function for each operation on the corresponding interface. For example, consider our Slice definition for the Greeter interface:
module VisitorCenter
{
interface Greeter
{
string greet(string name);
}
}
The Slice compiler generates the following classes for this interface:
namespace VisitorCenter
{
class Greeter : public virtual Ice::Object
{
public:
void dispatch(
IncomingRequest& request,
std::function<void(OutgoingResponse)> sendResponse) override;
virtual std::string greet(std::string name, const Ice::Current&) = 0;
// ...
};
class AsyncGreeter : public virtual Ice::Object
{
public:
void dispatch(
IncomingRequest& request,
std::function<void(OutgoingResponse)> sendResponse) override;
virtual void greetAsync(
std::string name,
std::function<void(std::string_view returnValue)> response,
std::function<void(std::exception_ptr)> exception,
const Ice::Current&) = 0;
// ...
};
// ...
}
The important points to note are:
As for the client side, Slice modules are mapped to C++ namespaces with the same name, so the skeleton class definition is nested in the namespace
VisitorCenter.The Slice compiler generates two skeleton classes: the default skeleton class has the same as the Slice interface (
Greeterwith our example), and the async skeleton class gets an additional Async prefix (AsyncGreeter).Each skeleton class contains a pure virtual member function for each operation in the Slice interface.
Each skeleton class is an abstract base class because its member functions are pure virtual.
Each skeleton class inherits from
Ice::Object(which forms the root of the Ice servant hierarchy).Each skeleton class reimplements (overrides) the
dispatchfunction defined onIce::Object.
Ice::Object Servant Base Class
The Slice pseudo-interface Object is mapped to the Ice::Object class in C++:
namespace Ice
{
class Object
{
public:
/// Dispatches an incoming request and returns the corresponding outgoing
/// response.
virtual void dispatch(
IncomingRequest& request,
std::function<void(OutgoingResponse)> sendResponse);
// ...
};
}
Object implements dispatch for the 4 operations on the Slice pseudo-interface Object: ice_ping, ice_isA, ice_id and ice_ids.
Servant Classes
In order to provide an implementation for an Ice object, you must create a servant class that inherits from one of the generated skeleton classes. For example, to create a servant for the Greeter interface, you could write:
#include "Greeter.h" // Slice-generated header
class Chatbot : public VisitorCenter::Greeter
{
public:
std::string greet(std::string name, const Ice::Current&) override;
};
Note that Chatbot derives from VisitorCenter::Greeter, one of the two generated skeleton classes.
As far as Ice is concerned, the Chatbot class must implement only a single member function: the pure virtual greet function that it inherits from its skeleton. This makes the servant class a concrete class that you can instantiate. You can add other member functions and data members as you see fit to support your implementation.
The async skeleton class is described in Asynchronous Method Dispatch (AMD) in C++.