예제 #1
0
파일: message.cpp 프로젝트: bsautron/libqi
 //convert args then call setValues
 void Message::setValues(const std::vector<qi::AnyReference>& in, const qi::Signature& expectedSignature, ObjectHost* context, StreamContext* streamContext) {
   qi::Signature argsSig = qi::makeTupleSignature(in, false);
   if (expectedSignature == argsSig) {
     setValues(in, context, streamContext);
     return;
   }
   if (expectedSignature == "m")
   {
     /* We need to send a dynamic containing the value tuple to push the
      * signature. This wraps correctly without copying the data.
      */
     std::vector<qi::TypeInterface*> types;
     std::vector<void*> values;
     types.resize(in.size());
     values.resize(in.size());
     for (unsigned i=0; i<in.size(); ++i)
     {
       types[i] = in[i].type();
       values[i] = in[i].rawValue();
     }
     AnyReference tuple = makeGenericTuplePtr(types, values);
     AnyValue val(tuple, false, false);
     encodeBinary(&_p->buffer, AnyReference::from(val), boost::bind(serializeObject, _1, context), streamContext);
     return;
   }
   /* This check does not makes sense for this transport layer who does not care,
    * But it checks a general rule that is true for all the messages we use and
    * it can help catch many mistakes.
    */
   if (expectedSignature.type() != Signature::Type_Tuple)
     throw std::runtime_error("Expected a tuple, got " + expectedSignature.toString());
   AnyReferenceVector nargs(in);
   SignatureVector src = argsSig.children();
   SignatureVector dst = expectedSignature.children();
   if (src.size() != dst.size())
     throw std::runtime_error("remote call: signature size mismatch");
   SignatureVector::iterator its = src.begin(), itd = dst.begin();
   boost::dynamic_bitset<> allocated(nargs.size());
   for (unsigned i = 0; i< nargs.size(); ++i, ++its, ++itd)
   {
     if (*its != *itd)
     {
       ::qi::TypeInterface* target = ::qi::TypeInterface::fromSignature(*itd);
       if (!target)
         throw std::runtime_error("remote call: Failed to obtain a type from signature " + (*itd).toString());
       std::pair<AnyReference, bool> c = nargs[i].convert(target);
       if (!c.first.type())
       {
         throw std::runtime_error(
               _QI_LOG_FORMAT("remote call: failed to convert argument %s from %s to %s", i, (*its).toString(), (*itd).toString()));
       }
       nargs[i] = c.first;
       allocated[i] = c.second;
     }
   }
   setValues(nargs, context, streamContext);
   for (unsigned i = 0; i< nargs.size(); ++i)
     if (allocated[i])
       nargs[i].destroy();
 }
예제 #2
0
파일: signal.cpp 프로젝트: cgestes/libqi
 SignalBase::SignalBase(const qi::Signature& sig, OnSubscribers onSubscribers)
   : _p(new SignalBasePrivate)
 {
   //Dynamic mean AnyArguments here.
   if (sig.type() != qi::Signature::Type_Dynamic && sig.type() != qi::Signature::Type_Tuple)
     throw std::runtime_error("Signal signature should be tuple, or AnyArguments");
   _p->onSubscribers = onSubscribers;
   _p->signature = sig;
 }
예제 #3
0
AnyReference Message::value(const qi::Signature &signature, const qi::TransportSocketPtr &socket) const {
    qi::TypeInterface* type = qi::TypeInterface::fromSignature(signature);
    if (!type) {
        qiLogError() <<"fromBuffer: unknown type " << signature.toString();
        throw std::runtime_error("Could not construct type for " + signature.toString());
        qiLogDebug() << "Serialized message body: " << _p->buffer.size();
    }
    qi::BufferReader br(_p->buffer);
    //TODO: not exception safe
    AnyReference res(type);
    return decodeBinary(&br, res, boost::bind(deserializeObject, _1, socket), socket.get());
}
예제 #4
0
 void SignatureConvertor::visit(const qi::Signature& sig) {
   switch(sig.type()) {
     case '[':
       visitList(sig);
       break;
     case '{':
       visitMap(sig);
       break;
     case '(':
       visitTuple(sig);
       break;
     case '#':
       visitVarArgs(sig);
       break;
     default:
       visitSimple(sig);
       break;
   }
 }