Visual C++ Tensorflow C10=] Wrapper 导致 LNK2019

VisualC++ Tensorflow C API Wrapper causes LNK2019

我目前正在编写 VisualC++ 12 Tensorflow Wrapper 以启用 Tensorflow 对象检测的推理任务 API。但是,我收到了一些类型为 LNK2019 ("unresolved external symbol") 的链接错误。

我研究了导致此错误的一些常见原因并发现了以下原因,但我无法在我的代码中发现任何这些原因(原因列在 The Microsoft reference for Linker Tool Error LNK2019 中)。

以下是导致错误的代码片段:

如果我评论这些行,我不会收到错误。

我已经包含了所有头文件并且没有收到任何编译器错误或警告,除了以下 5 个 LNK2019:

TensorflowInference.obj : error LNK2019: unresolved external symbol "public: class tf::TensorflowTensor::TensorView __cdecl tf::TensorflowTensor::View(void)" (??$View@M@TensorflowTensor@tf@@QEAA?AV?$TensorView@M@01@XZ) referenced in function "public: void __cdecl tf::TensorflowInference::detect(class cv::Mat const &,class std::vector > &)const " (?detect@TensorflowInference@tf@@QEBAXAEBVMat@cv@@AEAV?$vector@UDetection@tf@@V?$allocator@UDetection@tf@@@std@@@std@@@Z)

TensorflowInference.obj : error LNK2019: unresolved external symbol "public: float const & __cdecl tf::TensorflowTensor::TensorView::operator()(class std::array)const " (??R?$TensorView@M@TensorflowTensor@tf@@QEBAAEBMV?$array@_K@std@@@Z) referenced in function "public: void __cdecl tf::TensorflowInference::detect(class cv::Mat const &,class std::vector > &)const " (?detect@TensorflowInference@tf@@QEBAXAEBVMat@cv@@AEAV?$vector@UDetection@tf@@V?$allocator@UDetection@tf@@@std@@@std@@@Z)

TensorflowInference.obj : error LNK2019: unresolved external symbol "public: unsigned __int64 __cdecl tf::TensorflowTensor::TensorView::NumElements(void)const " (?NumElements@?$TensorView@M@TensorflowTensor@tf@@QEBA_KXZ) referenced in function "public: void __cdecl tf::TensorflowInference::detect(class cv::Mat const &,class std::vector > &)const " (?detect@TensorflowInference@tf@@QEBAXAEBVMat@cv@@AEAV?$vector@UDetection@tf@@V?$allocator@UDetection@tf@@@std@@@std@@@Z)

TensorflowInference.obj : error LNK2019: unresolved external symbol "public: class tf::TensorflowTensor::TensorView __cdecl tf::TensorflowTensor::View(void)" (??$View@M@TensorflowTensor@tf@@QEAA?AV?$TensorView@M@01@XZ) referenced in function "public: void __cdecl tf::TensorflowInference::detect(class cv::Mat const &,class std::vector > &)const " (?detect@TensorflowInference@tf@@QEBAXAEBVMat@cv@@AEAV?$vector@UDetection@tf@@V?$allocator@UDetection@tf@@@std@@@std@@@Z)

TensorflowInference.obj : error LNK2019: unresolved external symbol "public: float const & __cdecl tf::TensorflowTensor::TensorView::operator()(class std::array)const " (??R?$TensorView@M@TensorflowTensor@tf@@QEBAAEBMV?$array@_K@std@@@Z) referenced in function "public: void __cdecl tf::TensorflowInference::detect(class cv::Mat const &,class std::vector > &)const " (?detect@TensorflowInference@tf@@QEBAXAEBVMat@cv@@AEAV?$vector@UDetection@tf@@V?$allocator@UDetection@tf@@@std@@@std@@@Z)

主啊,那是一大堆文字,但我只包含了错误的重要行。

感谢任何帮助我解决这些错误的提示!我对 C++ 编程还是很陌生,尤其是模板仍然让我有些头疼。

C++ 编译器包括两个主要阶段:

  1. 编译:这是您的 *.cpp 文件变成 *.obj 文件的地方。此阶段后出现编译时错误。

如果没有发生编译时错误,构建过程将移至:

  1. 链接:这是将所有 obj 文件 link 连同任何依赖项(例如 lib/dll 文件)一起 lib/dll 以创建最终可执行文件的过程。如果缺少任何依赖项,您将收到 link 时间错误。

因此,考虑到这些信息,让我们看看您的错误: 'LNK2019'。这意味着它是一个link时间错误(用LNK表示),错误编号表示未解析的符号,并且在几个地方提到了TensorFlowTensor,这表明您刚刚发布的文件。

所以,发生的事情是 linker 找不到每个错误中指定的函数的定义。在这种非常特殊的情况下,这样做的原因是您已经在 cpp 文件中提供了模板函数的实现。

这会导致问题,因为模板函数必须内联定义,即在头文件中定义。

TensorflowTensor.cpp中的所有代码移动到TensorflowTensor.h,像这样:

namespace tf {
    class TensorflowTensor : public TensorflowCWrapper<TF_Tensor>
    {
    public:
      TensorflowTensor(const cv::Mat& input_image);
      TensorflowTensor(TF_Tensor* tensor);

      // inner class for convenient access to tensors' data
      template<typename DType, size_t D>
      class TensorView
      {
      public:
        TensorView<DType, D>(TensorflowTensor& tensor){
           // Constructor body goes here instead of cpp file.
        }
        const DType& operator()(std::array<size_t, D> n) const{
           // operator body goes here
        }
        DType& operator()(std::array<size_t, D> n){
           // Here too
        }
        size_t NumElements() const;

      private:
        DType* data_;
        std::array<size_t, D> dims_;
        size_t num_el_;
       };

      template<typename DType, size_t D>
      TensorView<DType, D> View();
    };
}

这样,编译器和 linker 就可以找到您要使用的函数的定义。