C++ Tensorflow 2.3构建C+时,机器生成文件中未解析的外部符号+;Windows上的项目

C++ Tensorflow 2.3构建C+时,机器生成文件中未解析的外部符号+;Windows上的项目,c++,tensorflow,C++,Tensorflow,我想知道是否有人在Windows上成功链接了Tensorflow 2.3 DLL。 我试图在一个小型的VS2019测试项目中集成一些TysFooFraseFund,看看是否可以使用TysFraseC++ API。 我设法用MSVC 14.16.27023构建tensorflow,并遵循官方链接中给出的说明: 我使用以下Bazel命令构建了.dll和.lib: bazel build--config=opt//tensorflow:tensorflow.dll bazel build

我想知道是否有人在Windows上成功链接了Tensorflow 2.3 DLL。 我试图在一个小型的VS2019测试项目中集成一些TysFooFraseFund,看看是否可以使用TysFraseC++ API。
  • 我设法用MSVC 14.16.27023构建tensorflow,并遵循官方链接中给出的说明:
  • 我使用以下Bazel命令构建了.dll和.lib:
    • bazel build--config=opt//tensorflow:tensorflow.dll
    • bazel build--config=opt//tensorflow:tensorflow.lib
  • VS2019项目属性:
    • 添加相关的
      附加包含目录
    • 添加
      附加库目录
      ,这是tensorflow source\bazel bin\tensorflow的唯一路径,其中
      bazel bin
      目录由生成系统生成(即bazel)
    • Linker->Input->其他依赖项中
      addgenerated
      tensorflow.lib
源代码很小,由我在Joe Antognini的书中查找到的几行代码组成:

正如Ashley Tharp所解释的,立即构建会导致链接器错误,抱怨无法解析的外部符号:

  • LNK2001未解析的外部符号“私有:类tensorflow::Scope uu cdecl tensorflow::Scope::WithOpNameImpl(
  • LNK2001未解析的外部符号“公共:静态类tensorflow::Scope uu cdecl tensorflow::Scope::NewRootScope(void)”
  • LNK2001未解析的外部符号“public:u cdecl tensorflow::Scope::~Scope(void)”
  • LNK2001未解析的外部符号“public:uu cdecl tensorflow::ops::Placeholder::Placeholder(
以下是她的导游的解释:

发生这种情况的原因是,在一个dll中只能公开60000个符号。这只是dll格式的一些限制。tensorflow库代码有60000多个符号,因此当程序员构建此dll时(dll只是用于在运行时访问库的二进制文件)如果还没有,你必须手动指出你想要公开的符号。谷歌已经选择了一些默认设置,但它可能不适用于所有人

而且,正如指南中所建议的,我进入了tensorflow标题,并用TF_导出宏预先添加了相关符号,这是您常用的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,就像这样
bazel build--config=opt//tensorflow:tensorflow.lib
,错误消失了

但是,当我尝试执行类似的操作来修复最后一个未解析的符号时,问题就出现了,即
占位符
。该符号位于
数组_ops.h
,这是一个机器生成的文件。因此,我在文件中编辑的任何内容都会在尝试构建.lib时被覆盖并丢失


问题:如何公开出现在机器生成文件中的符号?请使用正确方向的指针,也许我遗漏了一些明显的内容。

包含动态库tensorflow_cc.dll和导入库tensorflow_cc.dll的文件夹。if.lib还有两个文件:

  • tensorflow_filtered_def_file.def:包含导入符号
  • tensorflow_cc.dll-2.params:已生成所有库
现在,如果您在构建应用程序时有一些未解析的符号,您所要做的就是使用更新的tensorflow_filtered_def_file.def文件重建动态库。您必须向该文件添加缺少的符号,对于示例代码,它是:

EXPORTS
    ??1Scope@tensorflow@@QEAA@XZ
    ?NewRootScope@Scope@tensorflow@@SA?AV12@XZ
    ??0Placeholder@ops@tensorflow@@QEAA@AEBVScope@2@W4DataType@2@AEBUAttrs@012@@Z
    ?WithOpNameImpl@Scope@tensorflow@@AEBA?AV12@AEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z
    the rest symbols ...
更新.def文件后,可通过调用以下命令重建dll:

link.exe /nologo /DLL /SUBSYSTEM:CONSOLE -defaultlib:advapi32.lib -DEFAULTLIB:advapi32.lib 
   -ignore:4221 /FORCE:MULTIPLE /MACHINE:X64 
    @bazel-out/x64_windows-opt/bin/tensorflow/tensorflow_cc.dll-2.params /OPT:ICF /OPT:REF 
    /DEF:bazel-out/x64_windows-opt/bin/tensorflow/tensorflow_filtered_def_file.def /ignore:4070
在重建dll/lib之前,请删除这些文件(它们是只读的)


更多信息,请参阅rafix07评论。

问题很好,干得好!+1
link.exe /nologo /DLL /SUBSYSTEM:CONSOLE -defaultlib:advapi32.lib -DEFAULTLIB:advapi32.lib 
   -ignore:4221 /FORCE:MULTIPLE /MACHINE:X64 
    @bazel-out/x64_windows-opt/bin/tensorflow/tensorflow_cc.dll-2.params /OPT:ICF /OPT:REF 
    /DEF:bazel-out/x64_windows-opt/bin/tensorflow/tensorflow_filtered_def_file.def /ignore:4070