当前位置: 首页 > 知识库问答 >
问题:

构建一个使用协议缓冲区的Android可执行gRPC服务器(无APK)

宋鸿德
2023-03-14

我从这里编译了gRPC Android示例。

我想运行的程序作为可执行从adb外壳。

将这些行添加到grpc helloworld。抄送

#include <iostream>

int main() {
  std::cout << "qwerty" << std::endl;
  return 0;
}

这些行到它的CMakeLists.txt

add_executable(avocado
    src/main/cpp/grpc-helloworld.cc)

target_include_directories(avocado
  PRIVATE ${HELLOWORLD_PROTO_HEADERS})

target_link_libraries(avocado
  helloworld_proto_lib
  android
  ${log-lib})

然后我推送生成的可执行文件和libs文件,并尝试运行它:

LD_库_路径=/鳄梨

我得到了以下错误:

此程序是针对协议缓冲区运行库的3.0.0版本编译的,该版本与已安装的版本(3.5.1)不兼容。联系程序作者进行更新。如果您自己编译程序,请确保您的标头来自与链接时库相同的协议缓冲区版本。(版本验证失败在"out/soong/。中间体/框架/av/drm/libmedia adrm/libmedia adrm/android_arm64_armv8-a_kryo300_shared_core/gen/proto/框架/av/drm/libmedia adrm/原型/plugin_metrics.pb.cc"。)协议缓冲区运行时库的版本3.0.0,该版本与安装的版本(3.5.1)不兼容。联系程序作者进行更新。如果您自己编译程序,请确保您的标头来自与链接时库相同的协议缓冲区版本。(版本验证失败"out/soong/.中间体/框架/av/drm/libmedia adrm/libmedia adrm/android_arm64_armv8-a_kryo300_shared_core/gen/proto/框架/av/drm/libmedia adrm/原型/plugin_metrics.pb.cc"。)中止了

我做错了什么?

我们意识到有一个版本的原型库叫做libprotobuf-cpp-full.solibprotobuf-cpp-lite.so,似乎他们的版本是3.0.0。这与我们的版本(3.5.1)冲突,该版本编译成静态库或共享库。

共有1个答案

尉迟边浩
2023-03-14

我不太清楚为什么会这样。一旦链接器加载了helloworld_proto_lib,它就会覆盖所有加载的protobuf符号,并且由于某种原因,与你无关的另一个库崩溃了你的程序。但这并没有告诉你什么新鲜事。

有一种方法可以解决这个问题:

使mainextern"C",并可能更改其名称。例如:

 extern "C" int my_main() {
  std::cout << "qwerty" << std::endl;
  return 0;
}

这将包含可执行文件的实际main,它将动态加载库helloworld_proto_libgrpc helloworld。以下是如何做到这一点:

#include <iostream>
#include <android/dlext.h>
#include <dlfcn.h>

int main() {
  android_dlextinfo extinfo;
  extinfo.flags = ANDROID_DLEXT_FORCE_LOAD;

  void* proto_lib = android_dlopen_ext("/path/to/libhelloworld_proto_lib.so", RTLD_LAZY, &extinfo);
  void* helloworld = dlopen("/path/to/libgrpc-helloworld.so", RTLD_LAZY);
  int (*my_main)() = (int (*)())dlsym(helloworld, "my_main");

  return my_main();
}

来自#的android _dlopen _ext功能包括

设置后,不要使用stat(2)检查库是否已加载。

当由于某种原因多个ELF文件共享相同的文件名(例如,因为已经加载的库已被删除和覆盖)时,此标志允许强制加载库。

请注意,如果库的DT_SONAME与旧库的DT_SONAME相同,而其他库的DT_required list中有该SONAME,第一个库将用于解决任何依赖关系。

我认为黑体字解释了这个解决方案的工作原理。

由于您将动态加载helloworld_proto_lib,现在可以将其从可执行文件定义中删除,并且不需要任何proto头:

add_executable(avocado
    src/main/cpp/grpc-avocado.cc)

target_link_libraries(avocado
  android
  ${log-lib})

您现在可以构建,推送可执行文件avocado和两个库libgrpc-helloworld.solibhelloworld_proto_lib.so,并运行。你不需要LD_LIBRARY_PATH。祝你项目的其余部分好运!

 类似资料:
  • 我们接近100人。proto文件,其中每个文件可以定义大约10个IDL结构(如服务或消息)。 有没有一种方法可以可视化它们,包括引用(从一个文件到另一个文件)。例如类似于UML类图。 可能有可配置的可视化Java /C。 引用自https://developers.google.com/protocol-buffers/docs/overview 协议缓冲区现在是谷歌的通用数据语言——在撰写本文时

  • 我正在尝试构建一个同时使用Google协议缓冲区和使用Gradle的Kotlin的项目。我希望将proto文件编译成Java源代码,然后从我的Kotlin代码中调用它。 我的源文件是这样排列的: 这是我的构建。gradle文件: 当我运行时,我在期间收到一堆“未解决的引用”错误。之后,我可以看到没有生成Java源文件,因此似乎根本没有调用原始编译器。 如果我删除了apply插件:“kotlin”行

  • 据我所知,协议缓冲区主要用于控制服务器和客户端代码的项目。我的一般问题是——协议缓冲区能否用于将二进制消息序列化/反序列化到使用现有协议的服务器?所以,我的问题: > 如果协议缓冲区不支持本机微调现有协议的序列化/反序列化方式,那么可以通过扩展添加该功能吗?是否可以以某种方式添加序列化/反序列化方法可以识别的关键字?也许这可以通过扩展或修改protobuf csharp port或protobuf

  • 试图使用Ionic 4中的协议缓冲区进行编码 我已经下载了协议并用它来生成一堆_pb.js文件,每个. proto文件一个。很好。 首先关注原型示例。这是示例代码: 我做了一些更改以匹配我的文件。更改proto文件的名称。但是我的proto文件中没有包名称。所以我只是使用了消息名称。首先这是我的. proto文件的开头: 下面是我修改后的代码: 这似乎不起作用。我的控制台显示: 我相信我已经成功地

  • 问题内容: 我正在使用gSoap将旧式C 系统重构为SOA。我们遇到了一些性能问题(非常大的XML),因此我的领导要我看一下协议缓冲区。我做到了,它看起来非常酷(我们需要C 和Java支持)。但是协议缓冲区是仅用于序列化的解决方案,现在我需要将其发送到Java前端。从C ++和Java角度来看,我应该使用什么来通过HTTP(只是内部网络)发送那些序列化的内容? PS。另一个人试图加速我们的gSoa

  • 我试图在Windows上的Qt中使用google协议缓冲区。因此,我使用MingGW的msys从github编译了protobuf源代码。proto编译器(protoc)似乎工作得很好,但遗憾的是,它无法使用生成的。博士和。pb。从Qt环境中抄送文件。 将此添加到我的。pro文件: 但我仍然得到“未定义的引用…”当我试图编译这个类时,它使用了所有的方法。 代码必须正确,因为它在使用protoc和Q