首页 文章

VisualC Tensorflow C API Wrapper导致LNK2019

提问于
浏览
0

我目前正在编写一个VisualC 12 Tensorflow Wrapper来为Tensorflow Object Detection API启用推理任务 . 但是,我得到了LNK2019类型的一些链接错误(“未解析的外部符号”) .

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

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

  • 文件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);
    const DType& operator()(std::array<size_t, D> n) const;
    DType& operator()(std::array<size_t, D> n);
    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();
};
}
  • TensorflowTensor.cpp中的实现(仅导致链接器错误的行):
namespace tf {
// Constructors of TensorflowTensor are here

  template<typename DType, size_t D>
  TensorflowTensor::TensorView<DType, D>::TensorView(TensorflowTensor& tensor)
  {
    if (tensor.NumDims() != D)
    {
      throw std::runtime_error("Number of dimensions do not match!");
    }

    num_el_ = 1;
    for (size_t i = 0; i < D; ++i)
    {
      dims_[i] = tensor.Dim(i);
      num_el_ *= dims_[i];
    }

    if (tensor.NumBytes() != (num_el_ * sizeof(DType)))
    {
      throw std::runtime_error("Wrong TensorView!");
    }

    data_ = static_cast<DType*>(tensor.Bytes());
  }

  template<typename DType, size_t D>
  const DType& TensorflowTensor::TensorView<DType, D>::operator()(std::array<size_t, D> n) const
  {
    return data_[ComputeOffset(n)];
  }

  template<typename DType, size_t D>
  DType& TensorflowTensor::TensorView<DType, D>::operator()(std::array<size_t, D> n)
  {
    return data_[ComputeOffset(n)];
  }

  template<typename DType, size_t D>
  size_t TensorflowTensor::TensorView<DType, D>::NumElements() const
  {
    return num_el_;
  }

  template<typename DType, size_t D>
  TensorflowTensor::TensorView<DType, D> TensorflowTensor::View()
  {
    return TensorView<DType, D>(*this);
  }
}
  • 以下是我调用函数的行(在方法中: TensorflowInference::detect(* some args */) ):
const auto output_scores = result_tensors[0]->TensorflowTensor::View<float, 2>();
const auto output_boxes = result_tensors[1]->TensorflowTensor::View<float, 3>();
const auto output_classes = result_tensors[2]->TensorflowTensor::View<float, 2>();

// copy detections to the results vector
results.clear();
for (size_t i = 0; i < output_scores.NumElements(); ++i)
{
  if (output_scores({{0, i}}) > 0.)
  {
    results.emplace_back(output_classes({{ 0, i }}),
      output_scores({{ 0, i }}),
      output_boxes({{ 0, i, 1 }}),
      output_boxes({{ 0, i, 0 }}),
      output_boxes({{ 0, i, 3 }}),
      output_boxes({{ 0, i, 2 }}));
  }
}

如果我评论这些行,我不会得到错误 .

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

TensorflowInference.obj:错误LNK2019:未解析的外部符号“public:class tf :: TensorflowTensor :: TensorView __cdecl tf :: TensorflowTensor :: View(void)”(?? $ View @ M $ 01 @ TensorflowTensor @ tf @@ QEAA? AV?$ TensorView @ M $ 01 @ 01 @XZ)在函数“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:错误LNK2019:未解决的外部问题符号“public:float const&__cdecl tf :: TensorflowTensor :: TensorView :: operator()(class std :: array)const”(?? ?? R?$ TensorView @ M $ 01 @ TensorflowTensor @ tf @@ QEBAAEBMV?$ array @ _K $ 01 @ std @@@ Z)在函数“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:e rror LNK2019:未解析的外部符号“public:unsigned __int64 __cdecl tf :: TensorflowTensor :: TensorView :: NumElements(void)const”(?NumElements @?$ TensorView @ M $ 01 @ TensorflowTensor @ tf @@ QEBA_KXZ)在函数“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:错误LNK2019:未解析的外部符号“public:class tf :: TensorflowTensor :: TensorView __cdecl tf :: TensorflowTensor ::查看(无效)“(查看@M $ 02 @ TensorflowTensor @ tf @@ QEAA?AV?$ TensorView @ M $ 02 @ 01 @ XZ)在函数”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:错误LNK2019:未解析的外部符号“public: float const& cdecl tf :: TensorflowTensor :: TensorView :: operator()(class std :: array)const“(?? R?$ TensorView @ M $ 02 @ TensorflowTensor @ tf @@ QEBAAEBMV?$ array @ _K $ 02 @std @@@ Z)在函数“public:void __cdecl tf :: TensorflowInference :: detect(class cv :: Mat const&,class std :: vector>&)const”中引用(?detect @ TensorflowInference @ tf @@ QEBAXAEBVMat @ CV @@ AEAV?$ @载体@ UDetection TF @@ V'$ @分配器@ UDetection TF @@@ STD @@@ STD @@@ Z)

主啊,那是一面文字,但我只包括错误的重要线条 .

我感谢任何帮助我解决这些错误的提示!我对C编程还很陌生,特别是模板仍然给我带来了一些痛苦 .

1 回答

  • 1

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

    • 编译:这是* .cpp文件转换为* .obj文件的位置 . 此阶段后出现编译时错误 .

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

    • 链接:这是将所有obj文件与任何依赖项(如lib / dll文件)链接在一起,以创建最终的可执行文件 . 如果缺少任何依赖项,您将收到链接时错误 .

    因此,记住这些信息,让我们来看看你的错误:'LNK2019' . 这意味着它是一个链接时间错误(用LNK表示),错误号表示一个未解析的符号,在几个地方,提到TensorFlowTensor,它表示您刚刚发布的文件 .

    因此,正在发生的事情是链接器无法找到每个错误中指定的函数的定义 . 在这个非常具体的案例中,其原因在于您已在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();
        };
    }
    

    这样,编译器和链接器可以找到您要使用的函数的定义 .

相关问题