【发布时间】:2020-07-17 13:07:17
【问题描述】:
我想知道是否有人在 Windows 上成功链接了 Tensorflow 2.3 DLL。 我正在尝试在一个小型 VS2019 测试项目中集成一些 tensorflow 功能,看看我是否可以使用 tensorflow C++ API。
- 我设法使用 MSVC 14.16.27023 构建了 tensorflow,并按照官方链接中给出的说明进行操作:
- 我使用以下 Bazel 命令构建了 .dll 和 .lib:
bazel build --config=opt //tensorflow:tensorflow.dllbazel build --config=opt //tensorflow:tensorflow.lib
- VS2019项目属性:
- 添加相关
Additional Include Directories - 添加
Additional Library Directories,也就是path-to-tensorflow-source\bazel-bin\tensorflow,其中bazel-bin目录是构建系统生成的(即Bazel) - 在
Linker->Input->Additional Dependencies添加生成的tensorflow.lib
- 添加相关
源代码很小,由我在 Joe Antognini 的 example 中查找的几行代码组成:
#pragma once
#define NOMINMAX
#include "tensorflow/core/public/session.h"
#include "tensorflow/cc/ops/standard_ops.h"
int main()
{
tensorflow::Scope root = tensorflow::Scope::NewRootScope();
auto X = tensorflow::ops::Placeholder(root.WithOpName("x"), tensorflow::DT_FLOAT,
tensorflow::ops::Placeholder::Shape({ -1, 2 }));
}
正如 Ashley Tharp 的 guide 中所述,立即构建会导致链接器错误,并抱怨未解析的外部符号:
- LNK2001 无法解析的外部符号“private: class tensorflow::Scope __cdecl tensorflow::Scope::WithOpNameImpl(...
- LNK2001 未解析的外部符号“public: static class tensorflow::Scope __cdecl tensorflow::Scope::NewRootScope(void)”...
- LNK2001 未解析的外部符号“public: __cdecl tensorflow::Scope::~Scope(void)”...
- LNK2001 未解析的外部符号“public: __cdecl tensorflow::ops::Placeholder::Placeholder(...
这是她的导游的解释:
发生这种情况的原因是您只能在 dll 中公开 60,000 个符号。这只是 dll 格式的一些限制。 tensorflow 库代码有超过 60000 个符号,因此作为构建此 dll 的程序员(dll 只是用于在运行时访问库的二进制文件),您将必须手动指示要公开的符号(如果它们尚未公开)。 Google 选择了一些默认设置,但它可能并不适合所有人。
并且,按照指南中的建议,我进入了 tensorflow 标头,并在相关符号前添加了 TF_EXPORT 宏,这是您常用的 DLL 导入-导出模式:
#ifdef TF_COMPILE_LIBRARY
#define TF_EXPORT __declspec(dllexport)
#else
#define TF_EXPORT __declspec(dllimport)
#endif // TF_COMPILE_LIBRARY
上述解决方法适用于前 3 个错误:
// scope.h
~Scope(); // change to: TF_EXPORT ~Scope();
...
static Scope NewRootScope(); // change to: TF_EXPORT static Scope NewRootScope();
...
Scope WithOpNameImpl(const string& op_name) const; // change to TF_EXPORT Scope...
完成编辑后,我像bazel build --config=opt //tensorflow:tensorflow.lib那样重新运行bazel,错误消失了。
但是,当我尝试执行类似的操作来修复最后一个未解析的符号时,问题就出现了,即Placeholder。该符号位于array_ops.h,这是一个机器生成的文件。因此,一旦我尝试构建 .lib,我在文件中编辑的任何内容都会被覆盖并丢失。
问题:如何公开出现在机器生成文件中的符号?非常感谢您指出正确方向的指针,也许我遗漏了一些明显的东西。
【问题讨论】:
-
好问题,干得好! +1
标签: c++ tensorflow