使用Opencv和Tensorflow c ++时冲突Protobuf版本

H. *_*mad 10 c++ opencv protocol-buffers tensorflow

我目前正在尝试在非bazel项目中使用Tensorflow的共享库,因此我使用bazel从tensorflow创建一个.so文件.

但是当我启动一个同时使用Opencv和Tensorflow的c ++程序时,它会出现以下错误:

[libprotobuf FATAL external/protobuf/src/google/protobuf/stubs/common.cc:78]此程序是针对Protocol Buffer运行时库的2.6.1版编译的,它与已安装的版本(3.1.0)不兼容.请与程序作者联系以获取更新.如果您自己编译了程序,请确保您的标题来自与链接时库相同的Protocol Buffers版本.(版本验证在"/build/mir-pkdHET/mir-0.21.0+16.04.20160330/obj-x86_64-linux-gnu/src/protobuf/mir_protobuf.pb.cc"中失败.)终止在抛出实例后调用'谷歌:: protobuf的:: FatalException'

what():该程序是针对Protocol Buffer运行时库的2.6.1版编译的,它与已安装的版本(3.1.0)不兼容.请与程序作者联系以获取更新.如果您自己编译了程序,请确保您的标题来自与链接时库相同的Protocol Buffers版本.("/build/mir-pkdHET/mir-0.21.0+16.04.20160330/obj-x86_64-linux-gnu/src/protobuf/mir_protobuf.pb.cc"中的版本验证失败.)放弃(核心转储)

你能帮助我吗?

谢谢

小智 6

您应该使用链接器脚本重建 TensorFlow,以避免在 Bazel 创建的共享库中将第三方符号设为全局。这就是 TensorFlow 的 Android Java/JNI 库如何与设备上预安装的 protobuf 库共存(查看tensorflow/contrib/android中的构建规则以获取工作示例)

这是我从 Android 库中改编的一个 BUILD 文件,用于执行此操作:

package(default_visibility = ["//visibility:public"])

licenses(["notice"])  # Apache 2.0

exports_files(["LICENSE"])

load(
    "//tensorflow:tensorflow.bzl",
    "tf_copts",
    "if_android",
)

exports_files([
    "version_script.lds",
])

# Build the native .so.
# bazel build //tensorflow/contrib/android_ndk:libtensorflow_cc_inference.so \
#   --crosstool_top=//external:android/crosstool \
#   --host_crosstool_top=@bazel_tools//tools/cpp:toolchain \
#   --cpu=armeabi-v7a
LINKER_SCRIPT = "//tensorflow/contrib/android:version_script.lds"

cc_binary(
    name = "libtensorflow_cc_inference.so",
    srcs = [],
    copts = tf_copts() + [
        "-ffunction-sections",
        "-fdata-sections",
    ],
    linkopts = if_android([
        "-landroid",
        "-latomic",
        "-ldl",
        "-llog",
        "-lm",
        "-z defs",
        "-s",
        "-Wl,--gc-sections",
        "-Wl,--version-script",  # This line must be directly followed by LINKER_SCRIPT.
        LINKER_SCRIPT,
    ]),
    linkshared = 1,
    linkstatic = 1,
    tags = [
        "manual",
        "notap",
    ],
    deps = [
        "//tensorflow/core:android_tensorflow_lib",
        LINKER_SCRIPT,
    ],
)
Run Code Online (Sandbox Code Playgroud)

以及内容version_script.lds

{
  global:
    extern "C++" {
        tensorflow::*;
    };
  local:
    *;
};
Run Code Online (Sandbox Code Playgroud)

这将使tensorflow命名空间中的所有内容全局化并可通过库使用,同时隐藏重置并防止它与 protobuf 发生冲突。

(浪费了大量时间,所以我希望它有所帮助!)


Ken*_*rda 4

该错误表明该程序是使用.hprotobuf 2.6.1 中的标头(文件)编译的。这些标头通常位于/usr/include/google/protobuf或中/usr/local/include/google/protobuf,但它们也可能位于其他位置,具体取决于您的操作系统和程序的构建方式。您需要将这些标头更新到版本 3.1.0 并重新编译程序。

  • 嗯,该消息表明该程序是使用旧的 protobuf 标头编译的。我是写该错误消息的人,我可以向您保证这没有错误。您必须弄清楚程序如何以旧标头结束。另一种可能性是程序的构建系统将其自己的标头副本(版本错误)下载到本地构建中,而不是使用系统安装的副本。但我不知道。这里有无限的可能性。 (3认同)
  • 我在`/usr/local/include/google/protobuf`中有正确的标头.....我发现一些.so opencv文件依赖于`libprotobuf-lite.so.9`(位于` /usr/lib/x86_64-linux-gnu/`)。 (2认同)
  • @Bersan 需要明确的是,这不是 protobuf 特有的问题。Linux 上动态链接的本质使得将同一库的多个版本链接到同一进程中是不安全的,而 C++ 的本质使得新版本的 C++ 库几乎不可能提供向后兼容的 ABI。也就是说,未来的 protobuf 版本或许应该考虑使用 C++11 内联命名空间来解决这个问题;protobuf 首次发布时该功能不可用。 (2认同)