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 中)。
以下是导致错误的代码片段:
文件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 }}));
}
}
如果我评论这些行,我不会收到错误。
我已经包含了所有头文件并且没有收到任何编译器错误或警告,除了以下 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++ 编译器包括两个主要阶段:
- 编译:这是您的 *.cpp 文件变成 *.obj 文件的地方。此阶段后出现编译时错误。
如果没有发生编译时错误,构建过程将移至:
- 链接:这是将所有 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 就可以找到您要使用的函数的定义。
我目前正在编写 VisualC++ 12 Tensorflow Wrapper 以启用 Tensorflow 对象检测的推理任务 API。但是,我收到了一些类型为 LNK2019 ("unresolved external symbol") 的链接错误。
我研究了导致此错误的一些常见原因并发现了以下原因,但我无法在我的代码中发现任何这些原因(原因列在 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 }})); } }
如果我评论这些行,我不会收到错误。
我已经包含了所有头文件并且没有收到任何编译器错误或警告,除了以下 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++ 编译器包括两个主要阶段:
- 编译:这是您的 *.cpp 文件变成 *.obj 文件的地方。此阶段后出现编译时错误。
如果没有发生编译时错误,构建过程将移至:
- 链接:这是将所有 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 就可以找到您要使用的函数的定义。