简体   繁体   English

CMake链接器无法识别头文件

[英]CMake linker does not recognized the header file

I'm a beginner in the Linux programing and here is my issue. 我是Linux编程的初学者,这是我的问题。 My project is a OpenCV project written by C++ in Linux environment. 我的项目是Linux环境中C ++编写的OpenCV项目。 In order to compile, I use CMake to build a Makefile and run. 为了进行编译,我使用CMake构建Makefile并运行。 In order to make clear, I am also new in playing with CMake. 为了清楚起见,我也是与CMake合作的新手。

First, I have a main.cpp where starts everything: 首先,我有一个main.cpp文件,其中开始所有内容:

#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <cstdio>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <map>
#include <vector>
#include <cmath>
#include <dirent.h>
#include <algorithm>
#include <string.h>

using namespace std;

#include "constants.h"
#include "readData.cpp"
#include "features.cpp"
#include "featuresRGBD.cpp"

bool USE_HOG = true;

// print error message
void errorMsg(string message) {
    cout << "ERROR! " << message << endl;
    exit(1);
}

As we can see, I had included some predefined files as: constants.h, readData.cpp,features.cpp and featuresRGBD.cpp 如我们所见,我包含了一些预定义文件,例如:constants.h,readData.cpp,features.cpp和featuresRGBD.cpp

In constaints.cpp, I set up some constant variables: 在constaints.cpp中,我设置了一些常量变量:

const int SLEEP_TIME = 0;

const int JOINT_NUM = 11;
const int JOINT_DATA_ORI_NUM = 9;
const int JOINT_DATA_POS_NUM = 3;
const int JOINT_DATA_NUM = (JOINT_DATA_ORI_NUM+JOINT_DATA_POS_NUM);
const int JOINT_DATA_TYPE_NUM = 2; // two types : orientation and xyz position

const int TORSO_JOINT_NUM = 2;
const int HEAD_JOINT_NUM = 0;

const int POS_JOINT_NUM = 4;
const int POS_JOINT_DATA_NUM = 3;

const int POS_LEFT_HAND_NUM = 0;
const int POS_RIGHT_HAND_NUM = 1;
const int POS_LEFT_FOOT_NUM = 2;
const int POS_RIGHT_FOOT_NUM = 3;

const int X_RES = 320;
const int Y_RES = 240;
const int RGBD_data = 4;

// 30 fps
const int frameStoreNum = 66;
const int compareFrame[] = {0, -5, -9, -14, -20, -27, -35, -44, -54, -65};
const int compareFrameNum = sizeof(compareFrame)/sizeof(compareFrame[0]);

In readData.cpp, I implemented my method using with some constants in constants.cpp 在readData.cpp中,我使用了constants.cpp中的一些常量来实现我的方法

bool READ_FROM_PNG = true;

class readData {
private:

    int currentFrameNum;
    int currentFrameNum_RGBD;
    int lastFrame;

    string dataLocation;
    string dataLocation_mirrored;
    string fileName;
    string fileName_skeleton;
    string fileName_RGBD;
    string curActivity;
    map<string, string> data_act_map;
    ifstream* file;
    ifstream* file_RGBD;

    bool mirrored;

    // print error message
    void errorMsg(string message, bool exitProgram) {
        cout << "ERROR! " << message << endl;
        printf("\tcurrentFrameNum = %d\n", currentFrameNum);
        printf("\tcurrentFrameNum_RGBD = %d\n", currentFrameNum_RGBD);

        if (exitProgram) {
            exit(1);
        }
    }    

    void errorMsg(string message) {
        errorMsg(message, true);
    }



    bool parseChk(bool chk, bool skeleton) {
        if (!chk) {
            if (skeleton) {
                errorMsg("parsing error. (skeleton)", true); 
            } else {
                errorMsg("parsing error. (RGBD) - IGNORE THIS ERROR!! (all random dataset will hit this error)", false);
            }
            return false;
        }
        return true;
    }

    // read skeleton data file
    void prepareSkeletonData() {
        curActivity = data_act_map[fileName];

        if (!mirrored) {
            fileName_skeleton = dataLocation + fileName + ".txt";
        } else {
            fileName_skeleton = dataLocation_mirrored + fileName + ".txt";
        }

        printf("\tOpening \"%s\" (%s)\n", (char*)fileName_skeleton.c_str(), (char*)curActivity.c_str());
        file = new ifstream((char*)fileName_skeleton.c_str(), ifstream::in);
        currentFrameNum = -99;
    }

    void closeSkeletonData() {
        file->close();
        printf("\tskeleton file closed\n");
    }

    // return true if data retrieving was successful
    bool readNextLine_skeleton(double **data, double **pos_data, int **data_CONF, int *data_pos_CONF) {
        string line;        
        bool file_ended = true;

        if (getline(*file,line)) {
            file_ended=false;
            stringstream lineStream(line);
            string element;

            int jointCount=0;  
            int joint_dataCount = 0;

            int pos_jointCount = 0;      
            int pos_joint_dataCount = 0;

            parseChk(getline(lineStream, element, ','), true);
            currentFrameNum = atoi((char*)element.c_str());

            if (element.compare("END") == 0) {
                file_ended = true;
                return false;
            }

            while (getline(lineStream, element, ',')) {
                double e = strtod((char*)element.c_str(), NULL);

                if (jointCount < JOINT_NUM) {
                    data[jointCount][joint_dataCount] = e;
                    joint_dataCount++;

                    if (joint_dataCount == JOINT_DATA_ORI_NUM) {
                        parseChk(getline(lineStream, element, ','), true); // ori conf value
                        data_CONF[jointCount][0] = atoi((char*)element.c_str());
                    } else if (joint_dataCount >= JOINT_DATA_NUM) {
                        parseChk(getline(lineStream, element, ','), true); // pos conf value
                        data_CONF[jointCount][1] = atoi((char*)element.c_str());
                        jointCount++;
                        joint_dataCount = 0;
                    }

                } else {
                    // pos only joints
                    if (pos_jointCount >= POS_JOINT_NUM) {
                        errorMsg("PARSING ERROR!!!!!");
                    }
                    pos_data[pos_jointCount][pos_joint_dataCount] = e;
                    pos_joint_dataCount++;
                    if (pos_joint_dataCount >= POS_JOINT_DATA_NUM) {
                        parseChk(getline(lineStream, element, ','), true); // pos conf value
                        data_pos_CONF[pos_jointCount] = atoi((char*)element.c_str());

                        pos_jointCount++;
                        pos_joint_dataCount = 0;
                    }
                }
            }

            // check if there is more data in current frame..
            if (getline(lineStream, element,',')) {
                errorMsg("more data exist in skeleton data ..\n");
            }

        } 

        if (currentFrameNum == -99) {
            errorMsg("file does not exist or empty!!");
        }

        return !file_ended;
    }

    // read RGBD data file
    void prepareRGBDData() {
        fileName_RGBD = dataLocation + fileName + "_rgbd.txt";
        printf("\tOpening \"%s\" (%s)\n", (char*)fileName_RGBD.c_str(), (char*)curActivity.c_str());
        file_RGBD = new ifstream((char*)fileName_RGBD.c_str(), ifstream::in);
        currentFrameNum = -99;
    }

    void closeRGBDData() {
        file_RGBD->close();
        printf("\tRGBD file closed\n");
    }

    // return true if data retrieving was successful
    bool readNextPNG(int ***data) {
        stringstream ss;
        ss << currentFrameNum;
        fileName_RGBD = dataLocation + fileName + "/RGB_" + ss.str() +".png";
        string fileName_Depth = dataLocation + fileName + "/Depth_" + ss.str() +".png";
        if (currentFrameNum == 1) {
            printf("\tOpening \"%s\" and so forth..\n", 
                    (char*)fileName_RGBD.c_str());
            printf("\tOpening \"%s\" and so forth..\n", 
                    (char*)fileName_Depth.c_str());
        }

        // Load an image from file
        cv::Mat rgbImage = cv::imread((char*)fileName_RGBD.c_str(),1);
        cv::Mat colorArr[3];
        cv::split(rgbImage, colorArr);

        cv::Mat depthImage = cv::imread((char*)fileName_Depth.c_str(),-1);

        if (rgbImage.data == NULL) {
            printf("ERROR! Unable to open file %s.\n", (char*)fileName_RGBD.c_str());
            exit(1);
        }
        if (depthImage.data == NULL) {
            printf("ERROR! Unable to open file %s.\n", (char*)fileName_Depth.c_str());
            exit(1);
        }

        for (int y=0; y<Y_RES; y++){ 
            // opencv uses BGR order
            uchar* Bptr = colorArr[0].ptr<uchar>(y); 
            uchar* Gptr = colorArr[1].ptr<uchar>(y); 
            uchar* Rptr = colorArr[2].ptr<uchar>(y); 
            ushort* IRptr = depthImage.ptr<ushort>(y); 
            for(int x=0;x<X_RES; x++){
                // our data is stored in RGB order
                data[x][y][0] = Rptr[x]; 
                data[x][y][1] = Gptr[x]; 
                data[x][y][2] = Bptr[x]; 
                data[x][y][3] = IRptr[x];
            } 
        } 

        return true;
    }

    // return true if data retrieving was successful
    bool readNextLine_RGBD(int ***IMAGE) {
        string line;        
        char* line_c;
        bool file_ended = true;

        if (getline(*file_RGBD,line)) {
            file_ended = false;

            line_c = (char*)line.c_str();
            char* element = strtok(line_c, ",");
            if (element == NULL || strcmp(element,"END") == 0) {
                file_ended = true;
                return false;
            }
            currentFrameNum_RGBD = atoi(element);
            if (currentFrameNum != currentFrameNum_RGBD) {
                printf("skeleton: %d rgbd: %d\n", currentFrameNum, currentFrameNum_RGBD);
                errorMsg("FRAME NUMBER BETWEEN SKELETON AND RGBD DOES NOT MATCH!!!!!!!!! (READING RGBD)");
            }

            for (int y=0;y<Y_RES;y++) {
                for (int x=0;x<X_RES;x++) {   
                    for (int d = 0; d<RGBD_data; d++) {     

                        element = strtok(NULL, ",");  // passing NULL keeps tokenizing previous call
                        if (element == NULL) {
                            file_ended = true;
                            return false;
                        }
                        int e = atoi(element);

                        if (!mirrored) {
                            IMAGE[x][y][d] = e;
                        } else {
                            IMAGE[x][(Y_RES-1)-y][d] = e; 
                        }
                    }
                }
            }            

            // check if there is more data in current frame..
            element = strtok(NULL, ",");  
            if (element != NULL) {
                printf("line_c = %s\n", line_c);
                errorMsg("more data exist in RGBD data ..\n");

            }

        } 

        return !file_ended;
    }

public:



    // return true if data retrieving was successful
    bool readNextFrame(double **data, double **pos_data, int **data_CONF, int *data_pos_CONF, int ***IMAGE) {
        if (currentFrameNum % 100 == 0) {
            printf("\t\t(progress..) frame num = %d\n", currentFrameNum);
        }
        bool status = readNextLine_skeleton(data,pos_data, data_CONF, data_pos_CONF);
        if (!status) {
            printf("\t\ttotal number of frames = %d\n", lastFrame);
            return false;
        }

        bool status_RGBD;
        if (!READ_FROM_PNG) {
            status_RGBD = readNextLine_RGBD(IMAGE);
        } else {
            status_RGBD = readNextPNG(IMAGE);    
        }
        if (status_RGBD) {
            lastFrame = currentFrameNum;
        } else {
            printf("\t\ttotal number of frames = %d\n", lastFrame);
        }
        return status_RGBD;
    }

    readData(string dataLoc, string fileN, map<string, string> d_a_map, int i, bool mirrored, string dataLoc_mirrored) {
        if (!mirrored) {
            printf("%d. ", i);    
        } else {
            printf("%d(M). ", i);
        }
        dataLocation = dataLoc;
        dataLocation_mirrored = dataLoc_mirrored;
        fileName = fileN;
        data_act_map = d_a_map;
        this->mirrored = mirrored;

        prepareSkeletonData();
        if (!READ_FROM_PNG) {
            prepareRGBDData();
        }
    }

    readData() {

    }

    ~readData(){
        closeSkeletonData();
        if (!READ_FROM_PNG) {
            closeRGBDData();
        }
        printf("\n");
    }

};

And continues to other files, I also use some predefined constants. 并继续其他文件,我还使用了一些预定义的常量。 Then, I write the CMakeLists.txt in order to build the MakeFiles, like this: 然后,我编写CMakeLists.txt以构建MakeFiles,如下所示:

cmake_minimum_required(VERSION 2.8)
project( FeatureExtractor )
find_package( OpenCV REQUIRED )
add_executable( FeatureExtractor main.cpp readData.cpp features.cpp featuresRGBD.cpp HOG.cpp HOGFeaturesOfBlock.cpp)
target_link_libraries( FeatureExtractor ${OpenCV_LIBS} )

Since I read somewhere, they said that "CMake handles dependencies automatically so headers don't need to be listed" so I don't mention the header file (constaint.h) in the config CMakeLists.txt. 由于我在某处阅读,他们说“ CMake自动处理依赖关系,因此不需要列出头文件”,因此在配置CMakeLists.txt中没有提及头文件(constaint.h)。

Then, I met this error when I run the command to combine and build the Makefile 然后,当我运行命令以合并并生成Makefile时遇到了此错误

make
Scanning dependencies of target FeatureExtractor
[ 16%] Building CXX object CMakeFiles/FeatureExtractor.dir/main.cpp.o
[ 33%] Building CXX object CMakeFiles/FeatureExtractor.dir/readData.cpp.o
/home/minhthanh/Downloads/Test/readData.cpp:11:5: error: ‘string’ does not name a type
/home/minhthanh/Downloads/Test/readData.cpp:12:5: error: ‘string’ does not name a type
/home/minhthanh/Downloads/Test/readData.cpp:13:5: error: ‘string’ does not name a type
/home/minhthanh/Downloads/Test/readData.cpp:14:5: error: ‘string’ does not name a type
/home/minhthanh/Downloads/Test/readData.cpp:15:5: error: ‘string’ does not name a type
/home/minhthanh/Downloads/Test/readData.cpp:16:5: error: ‘string’ does not name a type
/home/minhthanh/Downloads/Test/readData.cpp:17:5: error: ‘map’ does not name a type
/home/minhthanh/Downloads/Test/readData.cpp:18:5: error: ‘ifstream’ does not name a type
/home/minhthanh/Downloads/Test/readData.cpp:19:5: error: ‘ifstream’ does not name a type
/home/minhthanh/Downloads/Test/readData.cpp:24:19: error: ‘string’ has not been declared
/home/minhthanh/Downloads/Test/readData.cpp:34:19: error: ‘string’ has not been declared
/home/minhthanh/Downloads/Test/readData.cpp:287:21: error: expected ‘)’ before ‘dataLoc’
/home/minhthanh/Downloads/Test/readData.cpp:317:2: error: expected ‘}’ at end of input
/home/minhthanh/Downloads/Test/readData.cpp: In member function ‘void readData::errorMsg(int, bool)’:
/home/minhthanh/Downloads/Test/readData.cpp:25:9: error: ‘cout’ was not declared in this scope
/home/minhthanh/Downloads/Test/readData.cpp:25:41: error: ‘endl’ was not declared in this scope
/home/minhthanh/Downloads/Test/readData.cpp:26:59: error: ‘printf’ was not declared in this scope
/home/minhthanh/Downloads/Test/readData.cpp:30:19: error: ‘exit’ was not declared in this scope
/home/minhthanh/Downloads/Test/readData.cpp: In member function ‘bool readData::parseChk(bool, bool)’:
/home/minhthanh/Downloads/Test/readData.cpp:43:59: error: invalid conversion from ‘const char*’ to ‘int’ [-fpermissive]
/home/minhthanh/Downloads/Test/readData.cpp:24:10: error:   initializing argument 1 of ‘void readData::errorMsg(int, bool)’ [-fpermissive]
/home/minhthanh/Downloads/Test/readData.cpp:45:119: error: invalid conversion from ‘const char*’ to ‘int’ [-fpermissive]
/home/minhthanh/Downloads/Test/readData.cpp:24:10: error:   initializing argument 1 of ‘void readData::errorMsg(int, bool)’ [-fpermissive]
/home/minhthanh/Downloads/Test/readData.cpp: In member function ‘void readData::prepareSkeletonData()’:
/home/minhthanh/Downloads/Test/readData.cpp:54:9: error: ‘curActivity’ was not declared in this scope
/home/minhthanh/Downloads/Test/readData.cpp:54:23: error: ‘data_act_map’ was not declared in this scope

Though it was a long list, I guess the problem is that some library and file I included in the main.cpp are not recognized in the below files (readData.cpp, features.cpp,...). 尽管列表很长,但我想问题是在以下文件(readData.cpp,features.cpp等)中无法识别我包含在main.cpp中的某些库和文件。

How can I config or modify in order to those files I include below could recognized those predefined files and libraries? 如何配置或修改我下面包含的那些文件才能识别那些预定义的文件和库?

The issue is that CMake compiles the readData.cpp separately and in there is no inclusion of <string> and using namespace std; 问题是CMake分别编译readData.cpp,并且不包含<string>using namespace std; in there, so it doesn't compile because of that. 在那里,所以它不会因此编译。

When you include readData.cpp, features.cpp, featuresRGBD.cpp etc. in main.cpp (which compiled as you can see) then you do not need to setup them in CMake for separate compilation, ie remove them from the CMake add_executable(... line. 当您在main.cpp中包含readData.cpp,features.cpp,featuresRGBD.cpp等(如您所见已编译)时,则无需在CMake中进行设置以进行单独的编译,即从CMake add_executable(...它们删除add_executable(...行。

But in general it is usual to do it the other way, ie compile each *.cpp separately, not include it in main.cpp, and #include ... in each of them just the stuff they need. 但是通常,通常以另一种方式进行操作,即分别编译每个* .cpp,而不在main.cpp和#include ...中分别包含它们所需的内容。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM