在协议缓冲区解码消息php

时间:2017-08-05 23:18:32

标签: php protocol-buffers proto3

我从c ++中的另一台服务器和php中的另一台服务器获得了protobuf消息(语法2),我收到了相同的protobuf消息(语法3)。现在我的目的是解码该消息。

以下是文件:

.proto文件:

syntax="proto3";
message ModuleDescriptor {
string name = 1;
string identifier = 2;
string version = 3;
float frequency = 4;
}
message RuntimeStatistic {
double sliceConsumption = 1;
}

message ModuleStatistic {
ModuleDescriptor module = 1;
RuntimeStatistic runtimeStatistic = 2;
}
message ModuleStatistics {
repeated ModuleStatistic moduleStatistics = 1; //this is the message that i receive
}

这个proto文件生成4个类。这是ModuleStatistics类:

<?php
# Generated by the protocol buffer compiler.  DO NOT EDIT!
# source: ModuleStatistics.proto

use Google\Protobuf\Internal\GPBType;
use Google\Protobuf\Internal\RepeatedField;
use Google\Protobuf\Internal\GPBUtil;

/**
* Protobuf type <code>ModuleStatistics</code>
*/
class ModuleStatistics extends \Google\Protobuf\Internal\Message
{
/**
 * <code>repeated .ModuleStatistic moduleStatistics = 1;</code>
 */
private $moduleStatistics;

public function __construct() {
    \GPBMetadata\ModuleStatistics::initOnce();
    parent::__construct();
}

/**
 * <code>repeated .ModuleStatistic moduleStatistics = 1;</code>
 */
public function getModuleStatistics()
{
    return $this->moduleStatistics;
}

/**
 * <code>repeated .ModuleStatistic moduleStatistics = 1;</code>
 */
public function setModuleStatistics(&$var)
{
    $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \ModuleStatistic::class);
    $this->moduleStatistics = $arr;
  }

}

index.php文件:

include_once './vendor/autoload.php';
require_once("generated_proto/GPBMetadata/ModuleStatistics.php");
require_once("generated_proto/ModuleDescriptor.php");
require_once("generated_proto/RuntimeStatistic.php");
require_once("generated_proto/ModuleStatistic.php");
require_once("generated_proto/ModuleStatistics.php");
...
$protoClass = new ModuleStatistics();      //MoudleStatitistics is a generated class from protobuff
$protoClass -> mergeFromString($receivedString);       //decode the string       received from the c++ server
echo $protoClass ->getModuleStatistics();       // getModuleStatisics() is a function in the generated class ModulseStatistics.
...

这是我对协议缓冲区的所有代码。

现在,当我尝试进入getModuleStatistics()函数时,它会抛出此错误:PHP Catchable fatal error: Object of class ModuleStatistics could not be converted to string in /app/index.php on line 41

mergeFromString()没有给我任何错误,但它也没有任何回溯。

我只收到proto文件的4条消息中的1条。但正如你可以看到它的嵌套消息。我需要收到所有4条消息吗?然后可能将它们设置为彼此?

1 个答案:

答案 0 :(得分:0)

更新

查看.proto文件,看起来您想要获得的实际数据仍然嵌套得更深......

从proto文件生成的PHP类的对象层次结构看起来有点像这样:

ModuleStatistics
    |
    +---- ModuleStatistic
    |         |
    |         +---- ModuleDescriptor
    |         |
    |         +---- RuntimeStatistic
    |
    +---- ModuleStatistic
              |
              +---- ModuleDescriptor
              |
              +---- RuntimeStatistic

也就是说ModuleStatistics是一个iterable对象可能,包含多个单独的ModuleStatistic个对象 - 零个或多个。

每个ModuleStatistic对象包含两个其他对象 -  ModuleDescriptorRuntimeStatistic,它们是包含您可能希望在程序中打印或以其他方式使用的实际数据的值对象。

这些对象包含数据的getter,我建议您阅读生成的PHP类,以熟悉为它们生成的特定接口。

总之,你应该能够做这样的事情来回应个别价值观:

// First, let's grab the return value from `getModuleStatistics()`
// which is a `ModuleStatistics` object

$moduleStatistics = $protoClass->getModuleStatistics();

// `ModuleStatistics` is an object that implements PHP's 
// `Iterator` interface, meaning you can iterate over it 
// with `foreach`. It will return zero or more nested 
// `ModuleStatistic` objects

foreach ($moduleStatistics as $moduleStatistic) {

    // Each `ModuleStatistic` itself contains two more nested
    // objects: `RuntimeStatistic` and `ModuleDescriptor`

    $runtimeStatistic = $moduleStatistic->getRuntimeStatistic();
    $moduleDescriptor = $moduleStatistic->getModule();

    // these nested objects contain the actual 
    // scalar values that you can echo

    echo $runtimeStatistic->getSliceConsumption(); // returns a double
    echo $moduleDescriptor->getName(); // returns a string
    echo $moduleDescriptor->getIdentifier(); // returns a string
    echo $moduleDescriptor->getVersion(); // returns a string
    echo $moduleDescriptor->getFrequency(); // returns a double
}

我显然没有测试过这段代码,因为我没有你的数据,所以YMMV。如果对方法的返回值有疑问,请阅读生成的代码或使用var_dump()print_r()来检查变量内容。

希望这有帮助。

关于以下错误:

  

PHP Catchable致命错误:第41行的/app/index.php中无法将ModuleStatistics类的对象转换为字符串

echo $protoClass ->getModuleStatistics();行正在返回您正在尝试ModuleStatistics的类echo的实例。

由于ModuleStatistics没有__toString()方法,因此无法做到这一点。因此要么不尝试echo对象,要么添加__toString()方法; e.g:

<?php

class ModuleStatistics
{
    // etc.

    public function __toString()
    {
        // `return` the desired string representation of your object here
    }
}

参考: