Paraview与VTK学习笔记(三)

下面接着上一面继续,上面那个函数最后调用了

vtkPVSessionCore::ExecuteStreamInternal

void vtkPVSessionCore::ExecuteStreamInternal(const vtkClientServerStream& stream,
                                             bool ignore_errors)
{
  LOG( << "----------------------------------------------------------------\n"
       << "ExecuteStream\n"
       << stream.StreamToString()
       << "----------------------------------------------------------------\n");

  this->Interpreter->ClearLastResult();//最后结果重置

  int temp = this->Interpreter->GetGlobalWarningDisplay();
  this->Interpreter->SetGlobalWarningDisplay(ignore_errors ? 0 : 1);
  this->Interpreter->ProcessStream(stream);//Interpreter是vtkClientServerInterpreter
  this->Interpreter->SetGlobalWarningDisplay(temp);
}

上面最后执行的四个函数,很显然又调用了vtkClientServerInterpreter类的实例Interpreter。

第一个函数,调用的是vtkClientServerInterpreter类的父类的函数,这个函数就是返回一个GetGlobalWarningDisplay量。让其等于temp

第二个函数,也是继承自父类vtkObject的函数,使其值为0或1。

第三个函数,ProcessStream(stream),调用的就是vtkClientServerInterpreter类的方法:

int vtkClientServerInterpreter::ProcessStream(const vtkClientServerStream& css)
{
  for(int i=0; i < css.GetNumberOfMessages(); ++i)
    {
    if(!this->ProcessOneMessage(css, i))
      {
      return 0;
      }
    }
  return 1;
}
我们再来回顾一下这条css的内容:

    stream << vtkClientServerStream::Invoke
           << VTKOBJECT(this)
           << "StillRender"
           << vtkClientServerStream::End;
然后我们再看this->ProcessOneMessage这个函数:

vtkClientServerInterpreter::ProcessOneMessage(const vtkClientServerStream& css,
                                              int message)
{
  // Log the message.
  if(this->LogStream)
    {
    *this->LogStream << "---------------------------------------"
                     << "---------------------------------------\n";
    *this->LogStream << "Processing ";
    css.PrintMessage(*this->LogStream, message);
    this->LogStream->flush();
    }

  // Look for known commands in the message.
  int result = 0;
  vtkClientServerStream::Commands cmd = css.GetCommand(message);//在这里获得cmd为Invoke命令,这里的message为第几条信息,为上一个函数的i
  switch(cmd)
    {
    case vtkClientServerStream::New:
      result = this->ProcessCommandNew(css, message); break;
    case vtkClientServerStream::Invoke:
      result = this->ProcessCommandInvoke(css, message); break;//执行
    case vtkClientServerStream::Delete:
      result = this->ProcessCommandDelete(css, message); break;
    case vtkClientServerStream::Assign:
      result = this->ProcessCommandAssign(css, message); break;
    default:
      {
      // Command is not known.
      vtksys_ios::ostringstream error;
      error << "Message with type "
            << vtkClientServerStream::GetStringFromCommand(cmd)
            << " cannot be executed." << ends;
      this->LastResultMessage->Reset();
      *this->LastResultMessage
        << vtkClientServerStream::Error << error.str().c_str()
        << vtkClientServerStream::End;
      } break;
    }

  // Log the result of the message.
  if(this->LogStream)
    {
    if(this->LastResultMessage->GetNumberOfMessages() > 0)
      {
      *this->LogStream << "Result ";
      this->LastResultMessage->Print(*this->LogStream);
     }
    else
      {
      *this->LogStream << "Empty Result\n";
      }
    this->LogStream->flush();
    }

  // If the command failed with an error message, invoke the error
  // event so observers can handle the error.
  if(!result)
    {
    this->InvokeEvent(vtkCommand::UserEvent, &info);
    }

  return result;
}
可以看到,这个函数最终调用了
 result = this->ProcessCommandInvoke(css, message)
其具体代码如下:

int
vtkClientServerInterpreter
::ProcessCommandInvoke(const vtkClientServerStream& css, int midx)//midx为
就为第几条信息,上一个函数的i{ // Create a message with all known id_value arguments expanded. vtkClientServerStream msg; if(!this->ExpandMessage(css, midx, 0, msg))//把这个信息膨胀 { // ExpandMessage left an error in the LastResultMessage for us. return 0; } // Now that id_values have been expanded, we do not need the last // result. Reset the result to empty before processing the message.

我们先来看ExpandMessage(css,midx,0,msg)这个函数,css即之前那条stream,midx为这条stream中的第几条信息,0为起始参数位置,out为建立的一个msg,下面这个函数应该就是要把stream扩展到这个out里,也可以说是对于一些特定参数需要解析添加
int vtkClientServerInterpreter::ExpandMessage(const vtkClientServerStream& in,
                                              int inIndex, int startArgument,
                                              vtkClientServerStream& out)
{
  // Reset the output and make sure we have input.
  out.Reset();
  if(inIndex < 0 || inIndex >= in.GetNumberOfMessages())
    {
    vtksys_ios::ostringstream error;
    error << "ExpandMessage called to expand message index " << inIndex
          << " in a stream with " << in.GetNumberOfMessages()
          << " messages." << ends;
    this->LastResultMessage->Reset();
    *this->LastResultMessage
      << vtkClientServerStream::Error << error.str().c_str()
      << vtkClientServerStream::End;
    return 0;
    }

  // Copy the command.
  out << in.GetCommand(inIndex);//把这条命令复制到out中

  // Just copy the first arguments.
  int a;
  for(a=0; a < startArgument && a < in.GetNumberOfArguments(inIndex); ++a)
    {
    out << in.GetArgument(inIndex, a);//把第一个参数存到out中,这里应该不执行,因为startArgument为0
    }

  // Expand id_value for remaining arguments.
  for(a=startArgument; a < in.GetNumberOfArguments(inIndex); ++a)//对于当前stream的当前信息获取其参数个数,每个参数进行for循环执行下面
    {
    if(in.GetArgumentType(inIndex, a) == vtkClientServerStream::id_value)//如果当前参数的参数类型为id_value
      {
      vtkClientServerID id;
      in.GetArgument(inIndex, a, &id);//在stream中获取一个指向类型/值的指针

      // If the ID is in the map, expand it.  Otherwise, leave it.如果ID在map,则扩展它,否则舍弃它
      if(const vtkClientServerStream* tmp = this->GetMessageFromID(id))
        {
        for(int b=0; b < tmp->GetNumberOfArguments(0); ++b)
          {
          out << tmp->GetArgument(0, b);
          }
        }
      else
        {
        out << in.GetArgument(inIndex, a);
        }
      }
    else if(in.GetArgumentType(inIndex, a) ==
            vtkClientServerStream::LastResult)//如果当前参数的类型是LastResult,则把之前的result的值(参数)传进out
      {
      // Insert the last result value.
      for(int b=0; b < this->LastResultMessage->GetNumberOfArguments(0); ++b)
        {
        out << this->LastResultMessage->GetArgument(0, b);
        }
      }
    else if (in.GetArgumentType(inIndex, a) ==
             vtkClientServerStream::stream_value)//如果当前参数的类型是stream_value
      {
      // Evaluate the expression and insert the result.
      vtkClientServerStream *lastResult = this->LastResultMessage;
      this->LastResultMessage = new vtkClientServerStream();
      vtkClientServerStream substream;
      in.GetArgument(inIndex, a, &substream);
      if (this->ProcessStream(substream))
        {
        // Insert the last result value.
        for(int b=0; b < this->LastResultMessage->GetNumberOfArguments(0); ++b)
          {
          out << this->LastResultMessage->GetArgument(0, b);//也把之前的result的值(参数)传进out
          }
        }
      // restore last-result
      delete this->LastResultMessage;
      this->LastResultMessage = lastResult;
      }
    else
      {
      // Just copy the argument.
      out << in.GetArgument(inIndex, a);//其他则只把这个参数复制进out
      }
    }

  // End the message.
  out << vtkClientServerStream::End;//从而得到一个完整的out

  return 1;
}
回顾一下这条stream:
    stream << vtkClientServerStream::Invoke
           << VTKOBJECT(this)
           << "StillRender"
           << vtkClientServerStream::End;
接下来我们看:
  this->LastResultMessage->Reset();//重置

  // Get the object and method to be invoked.
  vtkObjectBase* obj;
  const char* method;
  if(msg.GetNumberOfArguments(0) >= 2 &&//第一条信息如果除了开始的command和最后的end,如果还有大于等于2条的信息
     msg.GetArgument(0, 0, &obj) && msg.GetArgument(0, 1, &method))//第二条如果过是一个对象,并且第三个是一个方法。并且创建相应指针
    {
    // Log the expanded form of the message.
    if(this->LogStream)
      {
      *this->LogStream << "Invoking ";
      msg.Print(*this->LogStream);
      this->LogStream->flush();
      }

    // Find the command function for this object's type.
    if(obj && this->HasCommandFunction(obj->GetClassName()))//如果由这个对象,并且这个对象由这个方法,应该是利用xml去查
      {
      if (this->CallCommandFunction(obj->GetClassName(), obj, method, msg,//执行这个对象的这个方法
                                    *this->LastResultMessage))
        {
        return 1;
        }
      }
    else
      {
      // Command function was not found for the class.
      vtksys_ios::ostringstream error;
      const char* cname = obj? obj->GetClassName():"(vtk object is NULL)";
      error << "Wrapper function not found for class \"" << cname << "\"."
            << ends;
      *this->LastResultMessage
        << vtkClientServerStream::Error << error.str().c_str()
        << vtkClientServerStream::End;
      }
    }
  else
    {
    *this->LastResultMessage
      << vtkClientServerStream::Error <<
        "Invalid arguments to vtkClientServerStream::Invoke.  "
        "There must be at least two arguments.  The first must be an object "
        "and the second a string."
      << vtkClientServerStream::End;
    }
  return 0;
}
 我们来看这个函数:
this->CallCommandFunction(obj->GetClassName(), obj, method, msg,//执行这个对象的这个方法
                                    *this->LastResultMessage)

int
vtkClientServerInterpreter::CallCommandFunction(const char* cname,
                                                vtkObjectBase* ptr,
                                                const char* method,
                                                const vtkClientServerStream& msg,
                                                vtkClientServerStream& result)
{
  vtkClientServerInterpreterInternals::ClassToFunctionMapType::const_iterator f =
    this->Internal->ClassToFunctionMap.find(cname);

  if (f == this->Internal->ClassToFunctionMap.end())
    {
    vtkErrorMacro("Cannot find command function for \"" << cname << "\".");
    return 1;
    }

  const vtkClientServerInterpreterInternals::CommandFunction* n = f->second;

  vtkClientServerCommandFunction function = n->Function;
  void* ctx = n->Context ? n->Context->Context : 0;

  return function(this, ptr, method, msg, result, ctx);
}
这个看不明白,应该就是调用这个函数了。但是在vtkObject中并没有函数StillRender。这里有什么问题呢,我们看看VTKOBJECT(this)是什么。
这个this很显然是vtkSMRenderViewProxy这个对象。

你可能感兴趣的:(Paraview与VTK学习笔记(三))