# Call code path ¶

A call in libqi employs a very twisted code path before arriving to its destination. This section will try to decompose that path and explain what each part does.

## Method advertising ¶

As explained in Object type erasure , you must advertise your methods so that they can be used in type-erased contexts. When you advertise them, they are wrapped in an  AnyFunction  with  AnyFunction::from  .

That  from  function is defined in anyfunctionfactory.hxx and try to match the type you give it (a member function pointer, a boost function, etc) with  AnyFunctionMaker  . This will create a type interface for your function which implements  FunctionTypeInterface  which is defined in anyfunction.hpp .

When instantiating the  FunctionTypeInterfaceEq  , a mask is given to the constructor. This mask tells if each argument must be transfered by value or by pointer (see Pointer as pointer and pointer as value ). Bit 0 is for return type, other bits are for arguments.

 transformRef  adds the indirection for each argument that need it. Then the  makeCall  functions, defined by the  makeCall  macro call the function and cast each argument to the correct type. It should be possible to rewrite this code without using macros, only with meta programing.

The return value of the function is caught by  AnyReferenceCopy  which allocates a copy of the return value on the heap so that it can travel in a type-erased manner. It overrides its  operator,  as a trick to get the return value of the function and not having a compilation failure when the function returns  void  .

As we’ll see below, the return value is returned as an AnyReference which must be  destroy()  -ed by the caller.

## Calling a method on an AnyObject/GenericObject ¶

 AnyObject  re-exposes the interfaced of  GenericObject  through  GenericObjectBounce  , defined in object.hxx , from which it inherits.  GenericObject  has generic  call  and  async  methods defined in genericobject.hpp .

These method catch all their arguments by  AutoAnyReference  which is the same as  AnyReference  but with a templated constructor that calls  AnyReference::from  .  call  and  async  call  metaCall  which is another member function which adds a layer of type-erasure. They specify if the call must be synchronous or not and give the method name and the parameters. The signature of the return type is given for the compatibility layer that libqi provides for structures described in Struct extension .

From this point on, methods return a  Future<AnyReference>  which points to the return value of the called method. It is the responsibility of the caller to free it.

This first overload of  metaCall  (called by  call  and  async  ) takes a  nameWithOptionalSignature  . It will use the  MetaObject::findMethod  method, giving it that name and the arguments of the call, to resolve which overload must be called.  findMethod  then returns an integer which is the id of the method or  -1  if it couldn’t be found. In the latter case, it generates an error string with a meaningful error message. On success, it calls the other overload of  metaCall  which takes an integer and not a name. This last method just forwards the call to  ObjectTypeInterface::metaCall  .

The returned  Future<AnyReference>  may actually be a  Future<Future<T>>  , if the method returns a future and the call is made in async. As explained in About futures , a method can return a value or a future in a transparent way to the caller, so the nested future must be extracted. This is done through  extractFuture  and  adaptFutureUnwrap  , defined in futureadapter.hxx depending on the type of the call.

## Object type interface implementation ¶

The  metaCall  method has the following signature:



qi::Future<AnyReference> metaCall(
void* instance,
AnyObject context,
unsigned int method,
const GenericFunctionParameters& params,
MetaCallType callType = MetaCallType_Auto,
Signature returnSig = Signature());



The first argument is the storage, as described in Type system . The second argument is the  AnyObject  the call was made in. It is used to run the call in a specific  ExecutionContext  , associated to the  AnyObject  and to add stats and tracing to the  AnyObject  . It receives also the id of the method to be called, the arguments of the call in the form close to a  vector<AnyReference>  which must not be freed. The  callType  argument specifies if the user wanted the call to be synchronous or asynchronous. It is used only as a hint of what the user wants and it depends on the implementation of  metaCall  if the call is synchronous or not. For example, if the object has a strand, the call can not be synchronous. The last argument is the signature of the expected return value. It is used for structure compatibility.

One possible implementation is in staticobjecttype.cpp . This method checks that the method exists and that it will be able to convert the returned value to the expected value. If it can’t, it doesn’t do the call and just return an error.

The other implementation is very similar and is in dynamicobject.cpp .  DynamicObjectInterface::metaCall  actually calls  DynamicObject::metaCall  which does almost the same thing as  StaticObjectTypeBase::metaCall  .

After that, it gets the  ExecutionContext  on which to run the call. If the id of the method is small, it means the method belongs to  Manageable  which we’ll talk about later. Otherwise, the method belongs to the object.

In our case, the  metaCall  method prepends the  this  argument and calls the method  qi::metaCall  , which is the generic method which will execute the final call. It gives it the method to call as an  AnyFunction  .

## qi::metaCall ¶

This method is defined in anyobject.cpp . It first decides if the call must be synchronous or not. If the call is direct, it bounces to the  call  method directly. If the call is asynchronous, it posts a functor on the  ExecutionContext  which will call  call  when it’s called.

 call  will handle tracing and stats if they are enabled and trigger the appropriate signals. It will do the call itself through the  AnyFunction  and set the promise to the returned  AnyReference  .

## Remote objects ¶

Objects that reside in other processes through qimessaging are exposed through  RemoteObject  which inherits from  DynamicObject  and implements its own  metaCall  . It sends a message and returns a future that will be set when the call reply is received.