CMake链接器无法识别头文件

时间:2016-02-17 18:15:20

标签: c++ linux opencv makefile cmake

我是Linux编程的初学者,这是我的问题。 我的项目是C ++在Linux环境下编写的OpenCV项目。为了编译,我使用CMake构建一个Makefile并运行。为了说清楚,我也是玩CMake的新手。

首先,我有一个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);
}

正如我们所看到的,我已经包含了一些预定义文件:constants.h,readData.cpp,features.cpp和featuresRGBD.cpp

在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]);

在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");
    }

};

继续其他文件,我也使用一些预定义的常量。 然后,我编写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} )

由于我在某处阅读,他们说&#34; CMake自动处理依赖关系,因此不需要列出标题&#34;所以我没有在配置CMakeLists.txt中提到头文件(constaint.h)。

然后,当我运行命令来组合和构建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

虽然这是一个很长的列表,但我想问题是我在main.cpp中包含的一些库和文件在下面的文件中无法识别(readData.cpp,features.cpp,...)。

如何配置或修改以下我包含的文件可以识别那些预定义的文件和库?

1 个答案:

答案 0 :(得分:2)

问题是CMake单独编译readData.cpp,并且没有包含<string>using namespace std;,因此它不会编译。

当你在main.cpp中包含readData.cpp,features.cpp,featuresRGBD.cpp等时(你可以看到编译)然后你不需要在CMake中设置它们进行单独的编译,即从中删除它们CMake add_executable(...行。

但一般情况下通常以另一种方式执行,即分别编译每个* .cpp,不包括在main.cpp中,并且每个#include ...只包含他们需要的东西。