I am currently writing a VisualC++ 12 Tensorflow Wrapper to enable Inference Tasks for the Tensorflow Object Detection API. However, I get some linking errors of the Type LNK2019 ("unresolved external symbol").
I researched some usual causes for this error and found the following, but I am not able to spot any of these in my code (The causes are listed on The Microsoft reference for Linker Tool Error LNK2019).
Here are the code snippets, that cause the Error:
File TensorflowTensor.h:
namespace tf {
class TensorflowTensor : public TensorflowCWrapper
{
public:
TensorflowTensor(const cv::Mat& input_image);
TensorflowTensor(TF_Tensor* tensor);
// inner class for convenient access to tensors' data
template
class TensorView
{
public:
TensorView(TensorflowTensor& tensor);
const DType& operator()(std::arrayn) const;
DType& operator()(std::arrayn);
size_t NumElements() const;
private:
DType* data_;
std::arraydims_;
size_t num_el_;
};
template
TensorViewView();
};
}The Implementation in TensorflowTensor.cpp (only the lines, that cause the linker error):
namespace tf {
// Constructors of TensorflowTensor are here
template
TensorflowTensor::TensorView::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(tensor.Bytes());
}
template
const DType& TensorflowTensor::TensorView::operator()(std::array n) const
{
return data_[ComputeOffset(n)];
}
template
DType& TensorflowTensor::TensorView::operator()(std::array n)
{
return data_[ComputeOffset(n)];
}
template
size_t TensorflowTensor::TensorView::NumElements() const
{
return num_el_;
}
template
TensorflowTensor::TensorViewTensorflowTensor::View()
{
return TensorView(*this);
}
}And here are the lines from which i call the functions (In a method:
TensorflowInference::detect(* some args */)
):const auto output_scores = result_tensors[0]->TensorflowTensor::View
();
const auto output_boxes = result_tensors[1]->TensorflowTensor::View();
const auto output_classes = result_tensors[2]->TensorflowTensor::View();
// 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 }}));
}
}
I don't get the error if I comment these lines.
I have included all Header Files and don't get any compiler errors or warnings except for the following 5 LNK2019s:
TensorflowInference.obj : error LNK2019: unresolved external symbol "public: class tf::TensorflowTensor::TensorView __cdecl tf::TensorflowTensor::View(void)" (??$View@M$01@TensorflowTensor@tf@@QEAA?AV?$TensorView@M$01@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$01@TensorflowTensor@tf@@QEBAAEBMV?$array@_K$01@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$01@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$02@TensorflowTensor@tf@@QEAA?AV?$TensorView@M$02@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$02@TensorflowTensor@tf@@QEBAAEBMV?$array@_K$02@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)
Lord, that's a wall of text, but I included only the important lines for the error.
I appreciate any hint that helps me to solve these errors! I'm still quite new to C++ programming and especially the templates are still giving me some pain in the neck.
Answer
A C++ compiler comprises of two main stages:
- Compilation: This is where your *.cpp files are turned into *.obj files. Compile time errors appear after this stage.
If no compile time errors happen, the build process moves to:
- Linking: This is when all the obj files are linked together, along with any dependencies, such as lib/dll files, to create a final executable file. If any dependencies are missing, you will get link time errors.
So, with this information in mind, let's take a look at your error:
'LNK2019'. This means it is a link time error (denoted by LNK), and the error number signifies an unresolved symbol, and in several places, mentioning TensorFlowTensor, which indicates the file you have just posted.
So, what is happening is that the linker can't find the definition of the functions specified in each error. The reason for this, in this very specific case, is that you have provided the implementation for templated functions in a cpp file.
This will cause problems as template functions must be defined inline, i.e. in the header file.
Move all the code in TensorflowTensor.cpp
to TensorflowTensor.h
, like so:
namespace tf {
class TensorflowTensor : public TensorflowCWrapper
{
public:
TensorflowTensor(const cv::Mat& input_image);
TensorflowTensor(TF_Tensor* tensor);
// inner class for convenient access to tensors' data
template
class TensorView
{
public:
TensorView(TensorflowTensor& tensor){
// Constructor body goes here instead of cpp file.
}
const DType& operator()(std::array n) const{
// operator body goes here
}
DType& operator()(std::array n){
// Here too
}
size_t NumElements() const;
private:
DType* data_;
std::array dims_;
size_t num_el_;
};
template
TensorView View();
};
}
This way, the compiler and linker can find the definition of the functions you wish to use.
No comments:
Post a Comment