2

我从 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 条消息吗?然后也许将它们设置为彼此?

4

1 回答 1

1

更新

查看您的 .proto 文件,您想要获取的实际数据似乎仍然嵌套更深......

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

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

也就是说,ModuleStatistics一个可迭代的对象可能包含多个单独的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 致命错误:无法将类 ModuleStatistics 的对象转换为第 41 行 /app/index.php 中的字符串

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

它不能这样做,因为ModuleStatistics没有__toString()方法。所以要么不要尝试echo对象,要么添加__toString()方法;例如:

<?php

class ModuleStatistics
{
    // etc.

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

参考:

于 2017-08-06T00:01:38.593 回答